awk 中赋值的值、awk 中三元运算符的解析

gry*_*yyk 3 awk

我是 awk 新手并正在尝试使用它。当尝试使用三元运算符时,在某些时候我想在真实条件下执行两个操作,并且由于我找不到执行此操作的语法,因此我尝试在条件内走私两个操作之一以利用懒惰评价。

我有一个输入文件如下:

file.csv

A,B,C,D
1,,,
2,,,
3,,,
4,,,
5,,,
6,,,
7,,,
8,,,
Run Code Online (Sandbox Code Playgroud)

为了练习的目的,如果 A 小于 5,我想将 B 和 C 赋值为 0 ;如果 A 为 5 或更大,则 C 为 1。我想三元运算符是一种糟糕的方法,但这不是我的观点。

问题是:为什么下面的行会输出这个结果?awk 如何解析这个表达式?

awk '(FNR!=1){$1<5 && $3=0 ? $2=0 : $2=1}{print $0}' FS=, OFS=, file.csv

输出:

1,1,1,
2,1,1,
3,1,1,
4,1,1,
5,,,
6,,,
7,,,
8,,,
Run Code Online (Sandbox Code Playgroud)

我期望$3=0表达式被执行并计算为true,并且当条件 ( $1<5) 的第一部分为 false 时被跳过。

预期结果:

1,0,0,
2,0,0,
3,0,0,
4,0,0,
5,1,,
6,1,,
7,1,,
8,1,,
Run Code Online (Sandbox Code Playgroud)

额外的问题:我实际上可以使用三元运算符并根据条件值在其中执行几条指令吗?这只是一种不好的做法还是实际上不可能?

Rav*_*h13 5

第一个解决方案:您应该像这样的代码,用您显示的示例和尝试编写和测试。我使用三元运算符来检查第一个字段的值是否小于 5,并基于此处第二个和第三个字段的设置值。

awk '
BEGIN { FS=OFS="," }
FNR==1{
  print
  next
}
{
  $2=($1<5?0:$1)
  $3=($1<5?0:$3)
}
1
'  Input_file
Run Code Online (Sandbox Code Playgroud)

第二种解决方案(通用方法):如果您必须在程序中传递 N 个要检查的字段,那么最好创建一个函数并在那里进行检查和赋值,在这里再次使用三元运算符进行计算。

在哪里:

  • threshold是一个awk变量,分配给5您要与第一个字段进行比较的值。
  • fieldCompare在本例中又是一个awk包含的变量1,因为我们想要将第一个字段值与 5 进行比较。
  • checkValue是函数,其中字段编号(例如:23在本例中)与逗号分隔值一起传递,以便在函数内的单次检查中进行检查。
awk -v threshold="5" -v fieldCompare="1" '
function checkValue(fields){
  num=split(fields,arr,",")
  for(i=1;i<=num;i++){
    fieldNum = arr[i]
    $fieldNum = ($fieldCompare<threshold?0:$fieldNum)
  }
}
BEGIN { FS=OFS="," }
FNR==1{
  print
  next
}
checkValue("2,3")
1
'  Input_file
Run Code Online (Sandbox Code Playgroud)


The*_*ird 5

如果我看看预期的结果,第二个字段应该是一个。

如果字段 1 小于 5,则将字段 2 和 3 设置为零,否则将字段 2 设置为 1。

最后的}1结果为 true 并将打印整行。

awk 'BEGIN{FS=OFS=","}(FNR!=1){($1 < 5) ? $2=$3=0 : $2=1}1' file.csv
Run Code Online (Sandbox Code Playgroud)

输出

A,B,C,D
1,0,0,
2,0,0,
3,0,0,
4,0,0,
5,1,,
6,1,,
7,1,,
8,1,,
Run Code Online (Sandbox Code Playgroud)