在特定行中用 awk for 循环替换值

and*_*rec 2 sed awk shell-script

我想将第一、第三、第五行等所有字段中的值 3 和 4 分别替换为 0 和 1,直到以下数据集结束:

 2 4 3 0
 2 4 3 0
 3 0 4 4
 3 0 4 4
 4 2 4 3
 4 2 4 3
 2 3 4 2
 2 3 4 2
Run Code Online (Sandbox Code Playgroud)

所以,想要的结果是:

 2 1 0 0
 2 4 3 0
 0 0 1 1
 3 0 4 4
 1 2 1 0
 4 2 4 3
 2 0 1 2
 2 3 4 2
Run Code Online (Sandbox Code Playgroud)

我正在使用以下代码来做到这一点:

awk '{for (i = 1; i <= NR; i=(i+2)) 
    if($i == 3) {$i = 0}
    if($i == 4) {$i = 1} 
}
END {print $0}' b.temp
Run Code Online (Sandbox Code Playgroud)

但是,此代码的输出只是 b.temp 文件 (2 3 4 2) 最后一行中的值。

我怎样才能做到这一点?代码需要针对任意数量的行和字段。解决方案可以是 awk、sed 或 shell 脚本中的其他替代方法。

提前致谢

Qua*_*odo 5

使用 sed:

sed 'y/34/01/;n' file
Run Code Online (Sandbox Code Playgroud)

意思是:

  • 将这一行中的3和4替换为0和1并打印出来;
  • 获取下一行并打印;
  • 获取下一行并重复循环。

但是,如果数据包含,例如,14,将其转换为 11,这将失败。要解决这个问题,请选择

sed 's/\<4\>/1/g;s/\<3\>/0/g;n' file
Run Code Online (Sandbox Code Playgroud)

那些\<\>匹配单词的开头和结尾。


Adm*_*Bee 5

你的方法的问题是你只有一个print语句,在END块中。该$0块中的值是文件最后一行的内容。因此,您的awk代码只会打印文件的最后一行。

另请注意,除非在块之前有条件(例如仅适用于文件结尾),否则awk将操作应用于每一行。所以,你的代码会尝试检查第一,第三等领域每一行,如果它是或替换成或分别...但从来没有打印结果。{ ... }END3401

为了将规则应用于每条奇数行,您可以检查是否NR%2为 1(或只是非零):

awk 'NR%2{for (i=1;i<=NF;i++) if ($i==3 || $i==4) $i-=3}1' b.temp
Run Code Online (Sandbox Code Playgroud)

1,存在的一个规则的外面时,是一种awk用于“打印从所有变换所得的线执行”的简写符号。