Grep Combine e extraia

Grep Combine e extraia

Eu tenho um arquivo que contém linhas como

proto=tcp/http  sent=144        rcvd=52 spkt=3 
proto=tcp/https  sent=145        rcvd=52 spkt=3
proto=udp/dns  sent=144        rcvd=52 spkt=3

Preciso extrair o valor de proto que é tcp/http, tcp/https, udp/dns.

Até agora eu tentei isso, grep -o 'proto=[^/]*/'mas só consegui extrair o valor como proto=tcp/.

Responder1

Com grep -o, você terá que corresponder exatamente ao que deseja extrair. Como você não deseja extrair a proto=string, você não deve combiná-la.

Uma expressão regular estendida que corresponda tcpou udpseja seguida por uma barra e alguma string alfanumérica não vazia é

(tcp|udp)/[[:alnum:]]+

Aplicando isso em seus dados:

$ grep -E -o '(tcp|udp)/[[:alnum:]]+' file
tcp/http
tcp/https
udp/dns

Para ter certeza de que faremos isso apenas em linhas que começam com a string proto=:

grep '^proto=' file | grep -E -o '(tcp|udp)/[[:alnum:]]+'

Com sed, removendo tudo antes do primeiro =e depois do primeiro caractere em branco:

$ sed 's/^[^=]*=//; s/[[:blank:]].*//' file
tcp/http
tcp/https
udp/dns

Para ter certeza de que faremos isso apenas nas linhas que começam com a string proto=, você pode inserir a mesma etapa de pré-processamento grepacima ou pode usar

sed -n '/^proto=/{ s/^[^=]*=//; s/[[:blank:]].*//; p; }' file

Aqui, suprimimos a saída padrão com a -nopção e, em seguida, acionamos as substituições e uma impressão explícita da linha somente se a linha corresponder a ^proto=.


Com awk, usando o separador de campos padrão e, em seguida, dividindo o primeiro campo =e imprimindo o segundo bit dele:

$ awk '{ split($1, a, "="); print a[2] }' file
tcp/http
tcp/https
udp/dns

Para ter certeza de que faremos isso apenas nas linhas que começam com a string proto=, você pode inserir a mesma etapa de pré-processamento grepacima ou pode usar

awk '/^proto=/ { split($1, a, "="); print a[2] }' file

Responder2

Se você estiver no GNU grep (para a -Popção), poderá usar:

$ grep -oP 'proto=\K[^ ]*' file
tcp/http
tcp/https
udp/dns

Aqui combinamos a proto=string, para ter certeza de que estamos extraindo a coluna correta, mas depois a descartamos da saída com o \Ksinalizador.

O acima assume que as colunas são separadas por espaço. Se tabulações também forem um separador válido, você usaria \Spara corresponder aos caracteres que não são espaços em branco, então o comando seria:

grep -oP 'proto=\K\S*' file

Se você também deseja proteger contra campos de correspondência onde proto=há uma substring, como a thisisnotaproto=tcp/https, você pode adicionar limite de palavra da \bseguinte forma:

grep -oP '\bproto=\K\S*' file

Responder3

Usando awk:

awk '$1 ~ "proto" { sub(/proto=/, ""); print $1 }' input

$1 ~ "proto"garantirá que só tomaremos medidas nas linhas protoda primeira coluna

sub(/proto=/, "")irá remover proto=da entrada

print $1imprime a coluna restante


$ awk '$1 ~ "proto" { sub(/proto=/, ""); print $1 }' input
tcp/http
tcp/https
udp/dns

Responder4

Apenas outra grepsolução:

grep -o '[^=/]\+/[^ ]\+' file

E um semelhante sedimprimindo apenas o grupo capturado correspondente:

sed -n 's/.*=\([^/]\+\/[^ ]\+\).*/\1/p' file

informação relacionada