要对同一个输入文件进行多次传递,这个简单的情况可以正常工作:
$ 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
该/regexp/
运算符是一个如果$0
与正则表达式匹配则返回 1,否则返回 0 的运算符。
print /foo/ + /bar/
例如,您可以将其用作语句的一部分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
ifp==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)
它们都会调用$
运算符来扩展到第 p 个字段。
awk
使用(也称为)的 GNU 实现gawk
,您可以使用ARGIND
为每个参数递增的 which 而不必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
只有当您的输入文件非常大,大到无法放入内存时,这种情况才会失败。