Usando expressão regular(regex) para filtrar um arquivo de entrada

Estou com o seguinte problema. O pessoal da infraestrutura nos passou um log com os acessos a um servidor intranet, onde um padrão se repete: yyyy-MM-dd … //…

Estou lendo esse arquivo, linha a linha, e gravando um arquivo .csv de saída e para isso eu aplico na linha de entrada um replaceFirst("(....)-(..)-(..).+/(.+)/.+", "$3/$2/$1;$4") e grava em um arquivo de saída.
Está funcionando, mas gostaria de simplificar a REGEX usando algo como:
"\(d{4})-(\d\d)-(\d\d)\W+/(\w+)/.+", "$3/$2/$1;$4")

Por que não aceita \d - dígitos, \W - não alfanumérico, \w - alfabético e o quantificador {4} - exatamente quatro caracteres?

Alguém com experiência em usar expressão regular em Java para me ajudar?

  • Poderia dar o exemplo do arquivo de logo e sua formatação?
  • A partir da anterior colocar a formatação nova para o arquivo criado?

Talvez não precise de regex

2019-09-01 04:55:29 10.1.0.123 GET /sigma/doc/Sigma_GerenRes_200909_12_Receita_TipoReceita.pdf - 80 - 10.2.34.67 HTTP/1.0 Mozilla/4.0+(compatible;+MSIE+4.01;+Windows+NT;+MS+Search+6.0+Robot) - intranet 304 0 0 235 31

O caractere \ é um caractere de controle, então quando você for escrever a regex em um literal String, o \ tem que ser digitado como \\.
Então por exemplo o \d no literal String vai ser \\d, o \W vai ser \\W e assim por diante.

Exemplo:

String regex = "(\\d{4})-(\\d{2})-(\\d{2})\\W+/(\\w+)/.+";
String replace = "$3/$2/$1;$4";
linhaProcessada = linhaOriginal.replaceAll(regex, replace);

Só tem que conferir se a regex está de acordo com o que você precisa, a regex abaixo:

"(\\d{4})-(\\d{2})-(\\d{2})\\W+/(\\w+)/.+"

Significa:

<4 dígitos> - <2 dígitos> - <2 dígitos> <caractere não alfanumérico pelo menos 1 vez> / <caractere alfanumérico pelo menos 1 vez> / <qualquer caracteres pelo menos 1 vez>

A documentação da classe Pattern explica os padrões para construir as regex.

2 curtidas

Legal, a seguinte regex deve te atender:

"(\\d{4})-(\\d{2})-(\\d{2}).+ /(\\w+)/.+"
2 curtidas

Também pensei em usar substring ou split, mas acredito que a REGEX é mais apropriado.

Porque você acha isso?

Porque segue um padrão. A data vem no começo, mas não sei se o tamanho da string que representa o ip se altera e ainda nos casos em que o método não é GET, mas POST. Teria que testar isso.

Está se complicando a toa com regex, deixando o código mais complicado de ler sem necessidade.

1 curtida

Então não segue padrão … Só complica muitas vezes

Ok, me dê uma sugestão, você sugere algo como:

dia = linha.substring(8, 2);
mes = linha.substring(5, 2);
ano = linha.substring(0, 4);
data = dia + "/" + mes + "/" + ano;
if ( linha.instr("GET") != -1 ) {
     sistema = linha.substring(20, 4);
} else {
    sistema = linha.substring(21, 4);     
}

Seria usar Substring mesmo, já a lógica de programação fica a seu critério. Poderia extrair a data inteira e depois mandar o java converter pra Date se necessário, depende de qual vai ser o destino dessa data.

Pelo padrão de conteúdo do seu arquivo, também acredito que utilizar o replace com regex é mais prático do que ficar usando split e substring.

1 curtida

Estou pensando em usa um dicionário(HashMap) para acumular o acesso aos sistemas ao longo do mês e outro com um resumo. Algo como:
Sistema-dia         Acessos
ABCD-01/10         3
ABSD-02/10         15

ABCD-29/10         1
ABSD-30/10         13
e

**sistemas-setembro         acessos
ABCD                                   127
BCDE                                   203
CDEF                                   37
DEFG                                   302

WXYZ                                   42