Como filtrar as linhas com 2 valores semelhantes?

5

Eu quero filtrar as linhas com mesmo número - > mesmo número

deste texto

    [325194/777232]/var/cache/apt/srcpkgcache.bin:  100%  extents: 5 -> 1   [ OK ]
    [325195/777232]/var/cache/apt/pkgcache.bin: 100%  extents: 4 -> 1   [ OK ]
    [325255/777232]/var/cache/man/de/index.db:  100%  extents: 2 -> 2   [ OK ]
    [325521/777232]/var/log/syslog: 100%  extents: 7 -> 1   [ OK ]
    [325525/777232]/var/log/lastlog:    100%  extents: 2 -> 2   [ OK ]
    [325531/777232]/var/log/syslog.1:   100%  extents: 5 -> 1   [ OK ]
    [325572/777232]/var/log/kern.log:   100%  extents: 6 -> 1   [ OK ]
    [325589/777232]/var/log/auth.log:   100%  extents: 3 -> 1   [ OK ]
    [325621/777232]/var/log/faillog:    100%  extents: 2 -> 2   [ OK ]
    [325625/777232]/var/log/wtmp:   100%  extents: 3 -> 1   [ OK ]
    [325627/777232]/var/log/kern.log.1: 100%  extents: 2 -> 1   [ OK ]
    [325644/777232]/var/log/cups/access_log.1:  100%  extents: 2 -> 1   [ OK ]
    [325810/777232]/var/log/auth.log.1: 100%  extents: 2 -> 1   [ OK ]
    
por vv0iadyk 19.02.2018 / 12:05

3 respostas

10

Para obter as linhas que têm , o same_number - > padrão same_number :

grep -E '([[:digit:]]+)[[:blank:]]+->[[:blank:]]+[[:blank:]]'
  • -E ativa o ERE (expressão regular estendida)

  • ([[:digit:]]+) corresponde a um ou mais dígitos e coloca no grupo capturado 1

  • [[:blank:]]+ corresponde a um ou mais espaços brancos horizontais

  • -> corresponde literalmente

  • refere-se ao primeiro grupo capturado

  • [[:blank:]] corresponde a um espaço em branco depois disso

Você pode usar a lógica semelhante com outras ferramentas / idiomas populares de processamento de texto, como sed , awk , perl .

Para obter as linhas que não têm o padrão, adicione apenas a opção -v :

grep -vE '([[:digit:]]+)[[:blank:]]+->[[:blank:]]+[[:blank:]]'

Exemplo:

% cat file.txt
[325194/777232]/var/cache/apt/srcpkgcache.bin:  100%  extents: 5 -> 1   [ OK ]
[325195/777232]/var/cache/apt/pkgcache.bin: 100%  extents: 4 -> 1   [ OK ]
[325255/777232]/var/cache/man/de/index.db:  100%  extents: 2 -> 2   [ OK ]
[325521/777232]/var/log/syslog: 100%  extents: 7 -> 1   [ OK ]
[325525/777232]/var/log/lastlog:    100%  extents: 2 -> 2   [ OK ]
[325531/777232]/var/log/syslog.1:   100%  extents: 5 -> 1   [ OK ]
[325572/777232]/var/log/kern.log:   100%  extents: 6 -> 1   [ OK ]
[325589/777232]/var/log/auth.log:   100%  extents: 3 -> 1   [ OK ]
[325621/777232]/var/log/faillog:    100%  extents: 2 -> 2   [ OK ]
[325625/777232]/var/log/wtmp:   100%  extents: 3 -> 1   [ OK ]
[325627/777232]/var/log/kern.log.1: 100%  extents: 2 -> 1   [ OK ]
[325644/777232]/var/log/cups/access_log.1:  100%  extents: 2 -> 1   [ OK ]
[325810/777232]/var/log/auth.log.1: 100%  extents: 2 -> 1   [ OK ]

% grep -E '([[:digit:]]+)[[:blank:]]+->[[:blank:]]+[[:blank:]]' file.txt
[325255/777232]/var/cache/man/de/index.db:  100%  extents: 2 -> 2   [ OK ]
[325525/777232]/var/log/lastlog:    100%  extents: 2 -> 2   [ OK ]
[325621/777232]/var/log/faillog:    100%  extents: 2 -> 2   [ OK ]

% grep -vE '([[:digit:]]+)[[:blank:]]+->[[:blank:]]+[[:blank:]]' file.txt
[325194/777232]/var/cache/apt/srcpkgcache.bin:  100%  extents: 5 -> 1   [ OK ]
[325195/777232]/var/cache/apt/pkgcache.bin: 100%  extents: 4 -> 1   [ OK ]
[325521/777232]/var/log/syslog: 100%  extents: 7 -> 1   [ OK ]
[325531/777232]/var/log/syslog.1:   100%  extents: 5 -> 1   [ OK ]
[325572/777232]/var/log/kern.log:   100%  extents: 6 -> 1   [ OK ]
[325589/777232]/var/log/auth.log:   100%  extents: 3 -> 1   [ OK ]
[325625/777232]/var/log/wtmp:   100%  extents: 3 -> 1   [ OK ]
[325627/777232]/var/log/kern.log.1: 100%  extents: 2 -> 1   [ OK ]
[325644/777232]/var/log/cups/access_log.1:  100%  extents: 2 -> 1   [ OK ]
[325810/777232]/var/log/auth.log.1: 100%  extents: 2 -> 1   [ OK ]
    
por heemayl 19.02.2018 / 12:22
3

Você pode fazer isso com o GNU Awk ( gawk ).

Supondo que a entrada está armazenada em MY_FILE e você deseja ver apenas as linhas com os mesmos números , pode parecer com isso:

gawk '{match($0,/([[:digit:]]+)\s*->\s*([[:digit:]])+/,M);if(M[1]==M[2])print$0}' MY_FILE

Se você quiser remover linhas com números iguais e mostrar apenas aquelas com números diferentes , basta substituir o == por != :

gawk '{match($0,/([[:digit:]]+)\s*->\s*([[:digit:]])+/,M);if(M[1]!=M[2])print$0}' MY_FILE

Explicação:

gawk executará as instruções dentro das chaves para cada linha, que são:

match($0, /([[:digit:]]+)\s*->\s*([[:digit:]])+/, M) ; 
if(M[1] == M[2]) print$0

Isso significa que corresponda a expressão regular ([[:digit:]]+)\s*->\s*([[:digit:]])+ à linha inteira ( $0 ) e armazene o objeto / matriz de correspondência na variável M .

Em seguida, compare o conteúdo dos grupos de correspondências 1 e 2 (o número antes e depois da seta respectivamente) e imprima a linha inteira se eles forem iguais (se você usar == ) ou diferentes (se usar != ) .

    
por Byte Commander 19.02.2018 / 12:26
3

Você não precisa realmente da correspondência de expressão regular se os dados estiverem estruturados como campos delimitados.

No seu caso, o -> sempre aparece como o 5º campo delimitado por espaço em branco, então é suficiente testar os valores do 4º e 6º:

awk '$6 != $4' file

Se a posição do -> variar, você poderá fazer algo como

awk '{for(i=1;i<NF;i++) if ($i == "->" && $(i-1) != $(i+1)) {print; break}}' file

ou divida a linha em -> primeiro e, em seguida, divida as partes em ambos os lados no espaço em branco e teste o último campo da primeira parte em relação ao primeiro campo do segundo:

awk -F' -> ' '{
  n=split($1,a,/[ \t]+/); split($2,b,/[ \t]+/); if(b[1] != a[n]) print
}' file
    
por steeldriver 19.02.2018 / 14:30