使用 grep 或 sed 即时复制和修改复杂的行

complex line copying&modifying on-the-fly with grep or sed

有没有办法用 grep 或 sed 执行以下操作:读取文件的每一行,复制两次并修改每个副本:

原文:

X Y Z
A B C

新行:

Y M X
Y M Z
B M A
B M C

其中X,Y,Z,M都是整数,M是一个固定的整数(即2)我们边复制边注入!我想一个解决方案(如果有的话)会非常复杂,以至于人们(包括我)看到它后会开始流血!

当然;你可以写:

sed 's/\(.*\) \(.*\) \(.*\)/ M \n M /'
$ awk -v M=2 '{print ,M,; print ,M,;}' file
Y 2 X
Y 2 Z
B 2 A
B 2 C

工作原理

  • -v M=2

    这定义变量 M 的值为 2。

  • print ,M,

    这将打印第二列,然后是 M,然后是第一列。

  • print ,M,

    这将打印第二列,然后是 M,然后是第三列。

加长版

假设我们要处理任意数量的列,其中我们打印第一列和最后一列之间的所有列,然后打印 M,然后打印第一列,然后打印第一列和最后一列之间的所有列,然后打印 M,其次是最后一个。在这种情况下,使用:

awk -v M=2 '{for (i=2;i<NF;i++)printf "%s ",$i; print M,; for (i=2;i<NF;i++)printf "%s ",$i; print M,$NF;}' file

例如,考虑这个输入文件:

$ cat file2
X Y1 Y2 Z
A B1 B2 C

以上产生:

$ awk -v M=2 '{for (i=2;i<NF;i++)printf "%s ",$i; print M,; for (i=2;i<NF;i++)printf "%s ",$i; print M,$NF;}' file2
Y1 Y2 2 X
Y1 Y2 2 Z
B1 B2 2 A
B1 B2 2 C

代码的关键变化是添加了以下命令:

for (i=2;i<NF;i++)printf "%s "

此命令打印从 i=2 开始的所有列,即第 之后的第一个到 i=NF-1 的列 最后一个之前。代码在其他方面是相似的。

使用 bash 内置命令:

m=2; while read a b c; do echo "$b $m $a"; echo "$b $m $c"; done < file

输出:

Y 2 X
Y 2 Z
B 2 A
B 2 C