中かっこ内の条件

中かっこ内の条件

同じ入力ファイルに複数のパスを作成するには、次の簡単なケースがうまく機能します。

$ awk 'p==1{print $1}; p==2{print $2}; p==3{print $3}' p=1 infile p=2 infile p=3 infile

しかし、この変化は失敗しましたか?

$ awk 'p==1{/Jan/ {print $1}}; p==2{print $2}; p==3{print $3}' p=1 infile p=2 infile p=3 infile

私は次の用語を使用したくありません。

p==1 && /Jan/ {print $1}

(オリジナル)コードの読みやすい構造を維持したいからです。

各括弧内に条件付き用語を使用する方法は?

例:

$ cat infile
James   Exeter 48
Alex    Leeds  22
Jan     London 35

望ましい結果:

Jan
Exeter
Leeds
London
48
22
35

答え1

この演算子は、正規表現と一致する場合は1を返し、それ以外の場合は0を返す演算子/regexp/です。$0

print /foo/ + /bar/たとえば、orの一部として使用できますが、if (/foo/) print "match"inの一部として使用することは無効な構文であり、同じ方法で有効ではありません。CONDITIONCONDITION { ACTION }ACTION/foo/ {something}a == b {something}"whatever" {something}

あなたが望むもの:

awk '
  p==1 {
    if (/Jan/) print $1
    next
  }
  p==2 {print $2; next}
  p==3 {print $3; next}
  ' p=1 infile p=2 infile p=3 infile

nextまた、テストp==2に一致する呼び出しを避けるようにp==3注意してくださいp==1

ここでも次のことができます。

awk '{print $p}' p=1 infile p=2 infile p=3 infile

または、次の一致する/Jan/レコードのみを印刷しますp==1

awk 'p != 1 || /Jan/ {print $p}' p=1 infile p=2 infile p=3 infile

$は演算子なので、$por$ pまたは$ (p * 2 - p)orを使用できます。$ (field_to_print = p)両方とも$演算子を呼び出してpthフィールドに展開します。

awk(とも呼ばれる)のGNU実装を使用すると、直接設定を必要とせずに各引数に対して増分をgawk使用できます。ARGINDp

gawk 'ARGIND != 1 || /Jan/ {print $ARGIND}' infile infile infile

¹ または p == 0 の場合、全レコード

答え2

@StéphaneChazelas あなたの特定の質問に答えました。しかし、明らかにしたい場合は、必要な操作を実行するために入力ファイルに複数回パスする必要はなく、次のように一度だけパスする必要があります。

$ awk '/Jan/{print $1} {a=a $2 ORS; b=b $3 ORS} END{printf "%s%s", a, b}' infile
Jan
Exeter
Leeds
London
48
22
35

または、より一般的には、複数のフィールドに対して以下を実行します。

$ awk '/Jan/{print $1} {for (i=2; i<=NF; i++) a[i]=a[i] $i ORS} END{for (i=2; i<=NF; i++) printf "%s", a[i]}' infile
Jan
Exeter
Leeds
London
48
22
35

入力ファイルが大きすぎてメモリに収まらない場合にのみ失敗します。

関連情報