awkを使用して一致した正規表現パターンを印刷する方法は?


109

を使用awkして、ファイル内で正規表現パターンに一致する単語を見つける必要があります。

私は唯一のパターンと一致する単語を印刷したいです。

したがって、行にある場合、私は:

xxx yyy zzz

そしてパターン:

/yyy/

取得したいだけです:

yyy

編集:私は次のようなものを書くことができたクルミのおかげで:

awk '{
        for(i=1; i<=NF; i++) {
                tmp=match($i, /[0-9]..?.?[^A-Za-z0-9]/)
                if(tmp) {
                        print $i
                }
        }
}' $1

そして、これは私が必要としたものです:)どうもありがとう!


1
@maxtaldykin質問から自己回答を別の回答に移動していただけませんか?
ケノーブ2018

2
する必要はありません。「正規表現に一致する」という意味tmp=match($i, /regexp);if(tmp){}if(tmp ~ $i){}ので、できるはず~です。
JustinCB 2018年

回答:


148

これは非常に基本的です

awk '/pattern/{ print $0 }' file

awkpattern使用して検索するように要求//し、その行を出力します。この行は、デフォルトではレコードと呼ばれ、$ 0で示されます。少なくともドキュメントを読んでください。

一致した単語のみを印刷したい場合。

awk '{for(i=1;i<=NF;i++){ if($i=="yyy"){print $i} } }' file

49
printはデフォルトのアクションなので、これでawk '/pattern/' file十分です。
Johnsyweb

18
@Johnsyweb、はい、私はこの事実を知っています。marverixのような初心者にとって、それはより視覚的であることを意味しています。
くるみ

21
私はあなたの知識を疑いません。ただし、この情報は他の人がこの答えを見つけるのに役立つ場合があります。
Johnsyweb

2
注:for(a)「yyy」が正規表現であり、ストレート文字列ではない場合、および(b)その「yyy」がフィールド全体に一致しない場合、@ marverixは-loopを機能させるためにもう少し宿題が必要になります。記録。
Johnsyweb

8
それはそうではないでしょう$i=="yyy"。それは次のようになり$i ~ /yyy/、正規表現のために。
JustinCB 2018年

118

GNUのgrep -o動作をエミュレートしようとしているようです。これにより、各行の最初の一致のみが必要になります。

awk 'match($0, /regex/) {
    print substr($0, RSTART, RLENGTH)
}
' file

以下は、GNUのawk実装を使用した例です():

awk 'match($0, /a.t/) {
    print substr($0, RSTART, RLENGTH)
}
' /usr/share/dict/words | head
act
act
act
act
aft
ant
apt
art
art
art

記事を読むmatchsubstrRSTARTおよびRLENGTHawkマニュアル。

その後、これを拡張して、同じ行の複数の一致を処理することができます。


注意:最後の部分に答えるために、必要な構成要素はすべて くるみの答えと私自身の答えにあります。
Johnsyweb

すばらしい答えです。私は怠惰なのでここで説明をお願いします。しかし、それが私がAWKを使用している理由です!
lukas.pukenis 14

印刷以外の一致結果で何かしたい場合はどうすればよいですか?たとえば、すべての一致を配列に追加したいとします。
Evya2005

@ evya2005:Ron printを必要な割り当てに置き換えるだけです。
Johnsyweb 2017年

うまくいきません。印刷のみ。例を見せてもらえますか?
Evya2005 2017年

36

gawkはこれをアクションとして使用して、すべての行の一致する部分を取得できます。

{ if (match($0,/your regexp/,m)) print m[0] }

match(string、regexp [、array])arrayが存在する場合は、それをクリアしてから、arrayの0番目の要素をregexpで一致した文字列の全体に設定します。regexpに括弧が含まれている場合、配列の整数インデックス付き要素は、対応する括弧で囲まれた部分式に一致する文字列の部分を含むように設定されます。 http://www.gnu.org/software/gawk/manual/gawk.html#String-Functions


13

あなたが入力の最後の行にのみ関心があるとあなたが唯一の試合(シェルコマンドの要約行の例えば一部)を見つけることが予想される場合、あなたはまた、から採用され、この非常にコンパクトなコードを試すことができます正規表現マッチを印刷する方法`awk`を使用していますか?

$ echo "xxx yyy zzz" | awk '{match($0,"yyy",a)}END{print a[0]}'
yyy

または部分的な結果を持つより複雑なバージョン:

$ echo "xxx=a yyy=b zzz=c" | awk '{match($0,"yyy=([^ ]+)",a)}END{print a[1]}'
b

警告:awk match()3つの引数を持つ関数はにのみ存在しgawkmawk

これは、 後読み正規表現grepはなく、はawk。このソリューションでは、インストールに対する要件が低くなっています。

$ echo "xxx=a yyy=b zzz=c" | grep -Po '(?<=yyy=)[^ ]+'
b

なぜ「tail -n1」を追加したのですか?これはなくても問題なく動作するはずです。
Arthur Accioly 2018

1
@ArthurAccioly正しい。私はこの用語を使用して、pingコールから平均往復時間を抽出しました。これは、ping呼び出しがそこから来た場所です。それを発見するのに4年かかったことは面白いです;)
Daniel Alder

12

Perlがオプションの場合、これを試すことができます。

perl -lne 'print $1 if /(regex)/' file

大文字と小文字を区別しないマッチングを実装するには、i修飾子を追加します

perl -lne 'print $1 if /(regex)/i' file

試合後にすべてを印刷するには:

perl -lne 'if ($found){print} else{if (/regex(.*)/){print $1; $found++}}' textfile

試合と試合後のすべてを印刷するには:

perl -lne 'if ($found){print} else{if (/(regex.*)/){print $1; $found++}}' textfile

3

この状況では、sedの使用もエレガントです。例(行を一致したグループ「yyy」で置き換えます):

$ cat testfile
xxx yyy zzz
yyy xxx zzz
$ cat testfile | sed -r 's#^.*(yyy).*$#\1#g'
yyy
yyy

関連マニュアルページ:https : //www.gnu.org/software/sed/manual/sed.html#Back_002dreferences-and-Subexpressions


:sedの非GNUのためのソリューションは、このようなものであるsed -n 's/^.*\(yyy\).*$/\1/gp' < testfile
グリゴリーEntin

1
@GrigoryEntin-bsd sedは元の回答で問題なく動作します。POSIXでサポートされている拡張正規表現スイッチは-Eですが、FreeBSDでは少なくとも-rは-Eと同じです(-rは2010年に追加されました)。とにかく、-Eで試してください(gnu sedは4.3で-Eが追加されました)
Juan

3

トピック外で、これはgrepを使用しても実行できます。誰かがgrepソリューションを探している場合に備えて、ここに投稿してください

echo 'xxx yyy zzze ' | grep -oE 'yyy'

正規表現を使っても簡単に取得できます。まさに私が必要としたもの。ありがとう!
マーキー

これは私にとってはうまくいきます。私の場合は次のようになります:echo "web_port = 8080、shutdown_port = 8005" | grep -oE "web_port = [0-9] +"#8080を返す
Robb Tsang

0

探しているテキスト/パターン( "yyy"など)がどの列にあるかがわかっている場合は、その特定の列をチェックして一致するかどうかを確認し、印刷できます。

たとえば、次の内容のファイルが与えられた場合(asdf.txtと呼ばれる)

xxx yyy zzz

「yyy」のパターンに一致する場合にのみ2番目の列を印刷するには、次のようにします。

awk '$2 ~ /yyy/ {print $2}' asdf.txt

これは、次のように、2列目に「yyy」が含まれるすべての行にも基本的に一致することに注意してください。

xxx yyyz zzz
xxx zyyyz
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.