次の行を含むファイルがあります
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
文字列で始まる行でのみこれを実行するには、proto=
上記と同じ前処理ステップを挿入するか、次を使用できます。grep
sed -n '/^proto=/{ s/^[^=]*=//; s/[[:blank:]].*//; p; }' file
-n
ここでは、デフォルトの出力を抑制してから置換を実行し、その行が一致する場合にのみその行を明示的に印刷するオプションを使用します^proto=
。
の場合、デフォルトawk
のフィールド区切り文字を使用して最初のフィールドを分割し、=
2番目のビットを印刷します。
$ awk '{ split($1, a, "="); print a[2] }' file
tcp/http
tcp/https
udp/dns
文字列で始まる行でのみこれを実行するには、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