2017-09-10 17 views
0

awkの1つの列に複数のパターンを一致させる構文は何ですか?awkは列内の複数のパターンと一致します

c11 c21 c31 
c12 c22 c32 
c13 c23 c33 

2番目の列にc21とc22に一致する行を除外する方法。 grep

は、一つはこのような何かを行うことができます(それだけで2番目の列に一致させるために指定されていません):

> awk '$2 != /c21|c22/' bar.txt 
c11 c21 c31 
c12 c22 c32 
c13 c23 c33 

> awk '$2 != "c21" || $2 != "c22"' bar.txt 
c11 c21 c31 
c12 c22 c32 
c13 c23 c33 

> egrep -w -v "c21|c22" bar.txt 
c13 c23 c33 

私はawkで遊んでみましたが、無駄に

これを正しく行うには、適切なawkの構文は何ですか?

答えて

5
$2 != /c21|c22/ 

C21又はC22に$ 0を比較し、その結果が1又は0だから、他の値を有する $2について試験だされるかの 結果$2を比較している
$2 != ($0 ~ /c21|c22/) 

の省略形であります1より。

$2 != "c21" || $2 != "c22" 

は常に真である条件であるc22に等しくないc21又は$2と等しくない$2について試験されます。orは、あなたがしようとしている何$2

の任意の値のために、常に真であるので、その上の$ 2がC21であるならば、最初の条件($2 != "c21")が偽であるが、その後第二の条件($2 != "c22")が真であると - それについて考えてみよう書き込みには、次のとおりです。より堅牢

awk '$2 !~ /c21|c22/' 

か:

awk '$2 !~ /^(c21|c22)$/' 

、より簡単に(プラス、同じように頑強に)本当にその条件を記述する方法は次のとおりです。

awk '$2 !~ /^c2[12]$/' 

、あなたは文字列ではなく、正規表現の比較をやってみたかった場合、それは使い捨てスクリプト(私は私見はそれがより明確になり、より少ない否定記号の最初のを好む)だならば、あなたはこれらのいずれかの操作を行いたい:

awk '!($2 == "c21" || $2 == "c22")' 
awk '$2 != "c21" && $2 != "c22"' 

と、このそうでない場合:あなたは一度だけ$2を指定して、あなたがbのないことを意味しているより多くのテストする必要がある場合は、単に分割された文字列に他の値を追加することができますので、最後

awk 'BEGIN{split("c21 c22",t); for (i in t) vals[t[i]]} !($2 in vals)' 

は最高ですスクリプトの後半で比較を行う。

+1

この非常に完全な答えに対する私の受け入れられた答えを変更しました。素晴らしいウォークスルーに感謝します。 – PedroA

1

使用及び(&&)の代わりに、又は(||):

awk '$2 != "c21" && $2 != "c22"' bar.txt 

プリント:

c13 c23 c33 

C21が等しくC22がないので、列2のC21との線が印刷されます||のバージョンは、$ 2がc22に等しくなく、その逆もc22の行では逆になります。実際には、列2がc21とc22の両方に等しくないため、すべての行が印刷されるわけではありません。

+0

grepのような表記でこれを書いたことの略記はありますか? – PedroA

関連する問題