web-dev-qa-db-ja.com

AWK:ラインパターンからキャプチャされたグループにアクセスする

Awkコマンドがある場合

pattern { ... }

パターンはキャプチャグループを使用していますが、ブロックでキャプチャされた文字列にアクセスするにはどうすればよいですか?

201
rampion

それは散歩の思い出のレーンだった...

ずっと前にawkをPerlに置き換えました。

どうやらAWK正規表現エンジンはそのグループをキャプチャしません。

あなたは次のようなものを使用することを検討するかもしれません:

Perl -n -e'/test(\d+)/ && print $1'

-nフラグにより​​、Perlはawkのようにすべての行をループします。

146
Peter Tillemans

Gawkでは、match関数を使用して、括弧で囲まれたグループをキャプチャできます。

gawk 'match($0, pattern, ary) {print ary[1]}' 

例:

echo "abcdef" | gawk 'match($0, /b(.*)e/, a) {print a[1]}' 

cdを出力します。

問題の機能を実装するgawkの特定の使用に注意してください。

移植可能な代替手段として、match()およびsubstrを使用して同様の結果を達成できます。

例:

echo "abcdef" | awk 'match($0, /b[^e]*/) {print substr($0, RSTART+1, RLENGTH-1)}'

cdを出力します。

290
glenn jackman

これは常に必要なものなので、bash関数を作成しました。それはグレンジャックマンの答えに基づいています。

定義

これを.bash_profileなどに追加します。

function regex { gawk 'match($0,/'$1'/, ary) {print ary['${2:-'0'}']}'; }

使用法

ファイル内の各行の正規表現をキャプチャする

$ cat filename | regex '.*'

ファイル内の各行の最初の正規表現キャプチャグループをキャプチャする

$ cat filename | regex '(.*)' 1
27
opsb

GNU awkを使用できます。

$ cat hta
RewriteCond %{HTTP_Host} !^www\.mysite\.net$
RewriteRule (.*) http://www.mysite.net/$1 [R=301,L]

$ gawk 'match($0, /.*(http.*?)\$/, m) { print m[1]; }' < hta
http://www.mysite.net/
12
Dan Ellis

拡張機能なしで、Vanilla awkでのキャプチャもシミュレートできます。ただし、直感的ではありません:

手順1. gensubを使用して、文字列に表示されない文字で一致を囲みます。ステップ2.キャラクターに対してsplitを使用します。手順3.分割された配列内の他のすべての要素がキャプチャグループです。

 $ echo 'ab cb ad' | awk '{split(gensub(/ a ./、SUBSEP "&" SUBSEP、 "g"、$ 0)、cap、SUBSEP);印刷キャップ[2] "|" cap [4]; } '
 ab | ad 
3
ydrol

Peter Tillemansの答えをラップするbash関数を思い付くのに少し苦労しましたが、ここに私が思いついたものがあります:

関数正規表現{Perl -n -e "/ $ 1/&& printf \"%s\n\"、" '$ 1'}

「ms」を出力したくないので、次の正規表現引数については、これはopsbのawkベースのbash関数よりも優れていることがわかりました。

'([0-9]*)ms$'
0
wytten