大括号内的条件

大括号内的条件

要对同一个输入文件进行多次传递,这个简单的情况可以正常工作:

$ 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的一部分是无效语法,同样的方式或在那里也是无效的。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==2p==3ifp==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)它们都会调用$运算符来扩展到第 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

只有当您的输入文件非常大,大到无法放入内存时,这种情况才会失败。

相关内容