我有一個文件,其中包含以下行
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
我需要提取 proto 的值,即tcp/http
, tcp/https
, udp/dns
。
到目前為止,我已經嘗試過此操作grep -o 'proto=[^/]*/'
,但只能將值提取為proto=tcp/
.
答案1
使用grep -o
,您必須完全匹配您想要提取的內容。由於您不想提取字串proto=
,因此不應匹配它。
tcp
匹配或udp
後跟斜杠和一些非空字母數字字串的擴展正則表達式是
(tcp|udp)/[[:alnum:]]+
將其應用於您的數據:
$ grep -E -o '(tcp|udp)/[[:alnum:]]+' file
tcp/http
tcp/https
udp/dns
為了確保我們只在以字串開頭的行上執行此操作proto=
:
grep '^proto=' file | grep -E -o '(tcp|udp)/[[:alnum:]]+'
使用,刪除第一個空白字元sed
之前和之後的所有內容:=
$ sed 's/^[^=]*=//; s/[[:blank:]].*//' file
tcp/http
tcp/https
udp/dns
為了確保我們只在以 string 開頭的行上執行此操作,您可以插入與上面proto=
相同的預處理步驟,或者您可以使用grep
sed -n '/^proto=/{ s/^[^=]*=//; s/[[:blank:]].*//; p; }' file
在這裡,我們使用選項抑制預設輸出-n
,然後僅當該行匹配時才觸發替換並明確列印該行^proto=
。
對於awk
,使用預設的欄位分隔符,然後拆分第一個欄位=
並列印它的第二位元:
$ awk '{ split($1, a, "="); print a[2] }' file
tcp/http
tcp/https
udp/dns
為了確保我們只在以 string 開頭的行上執行此操作,您可以插入與上面proto=
相同的預處理步驟,或者您可以使用grep
awk '/^proto=/ { split($1, a, "="); print a[2] }' file
答案2
如果您使用 GNU grep (對於-P
選項),您可以使用:
$ grep -oP 'proto=\K[^ ]*' file
tcp/http
tcp/https
udp/dns
這裡我們匹配proto=
字串,以確保我們提取正確的列,但隨後我們使用標誌將其從輸出中丟棄\K
。
上面假設列是用空格分隔的。如果製表符也是有效的分隔符,您將使用它\S
來匹配非空白字符,因此命令將是:
grep -oP 'proto=\K\S*' file
如果您還想防止匹配字段,其中proto=
是 子字串,例如 a thisisnotaproto=tcp/https
,您可以添加單字邊界,\b
如下所示:
grep -oP '\bproto=\K\S*' file
答案3
使用awk
:
awk '$1 ~ "proto" { sub(/proto=/, ""); print $1 }' input
$1 ~ "proto"
proto
將確保我們只對第一列中的行採取行動
sub(/proto=/, "")
proto=
將從輸入中刪除
print $1
列印剩餘的列
$ awk '$1 ~ "proto" { sub(/proto=/, ""); print $1 }' input
tcp/http
tcp/https
udp/dns
答案4
只是另一個grep
解決方案:
grep -o '[^=/]\+/[^ ]\+' file
以及類似的sed
僅列印匹配的捕獲組:
sed -n 's/.*=\([^/]\+\/[^ ]\+\).*/\1/p' file