同じ入力ファイルに複数のパスを作成するには、次の簡単なケースがうまく機能します。
$ 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の一部として使用することは無効な構文であり、同じ方法で有効ではありません。CONDITION
CONDITION { 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
$
は演算子なので、$p
or$ p
または$ (p * 2 - p)
orを使用できます。$ (field_to_print = p)
両方とも$
演算子を呼び出してpthフィールドに展開します。
awk
(とも呼ばれる)のGNU実装を使用すると、直接設定を必要とせずに各引数に対して増分をgawk
使用できます。ARGIND
p
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
入力ファイルが大きすぎてメモリに収まらない場合にのみ失敗します。