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 tcp
ou udp
seja 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 grep
acima ou pode usar
sed -n '/^proto=/{ s/^[^=]*=//; s/[[:blank:]].*//; p; }' file
Aqui, suprimimos a saída padrão com a -n
opçã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 grep
acima ou pode usar
awk '/^proto=/ { split($1, a, "="); print a[2] }' file
Responder2
Se você estiver no GNU grep (para a -P
opçã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 \K
sinalizador.
O acima assume que as colunas são separadas por espaço. Se tabulações também forem um separador válido, você usaria \S
para 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 \b
seguinte 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 proto
da primeira coluna
sub(/proto=/, "")
irá remover proto=
da entrada
print $1
imprime a coluna restante
$ awk '$1 ~ "proto" { sub(/proto=/, ""); print $1 }' input
tcp/http
tcp/https
udp/dns
Responder4
Apenas outra grep
solução:
grep -o '[^=/]\+/[^ ]\+' file
E um semelhante sed
imprimindo apenas o grupo capturado correspondente:
sed -n 's/.*=\([^/]\+\/[^ ]\+\).*/\1/p' file