AWK或sed粘贴非相邻线的方式

AWK或sed粘贴非相邻线的方式,awk,sed,Awk,Sed,以下AWK命令将在“ddd eee”行的末尾粘贴“mmm”行。使用AWK或sed有更简单的方法吗 $ cat file aaa bbb ccc ddd eee jjj kkk lll mmm nnn ooo ppp 澄清一下:我想将第4行粘贴到这个特定文件的第2行末尾,在“ddd eee”和“mmm”之间留一个空格。这就是任务。有没有比我提出的更简单的AWK或sed解决方案?解决方案: 这可以在sed中使用保留空间完成: $ txr -c '@line1 @line2 @line3 @line

以下AWK命令将在“ddd eee”行的末尾粘贴“mmm”行。使用AWK或sed有更简单的方法吗

$ cat file
aaa bbb ccc
ddd eee
jjj kkk lll
mmm
nnn ooo ppp
澄清一下:我想将第4行粘贴到这个特定文件的第2行末尾,在“ddd eee”和“mmm”之间留一个空格。这就是任务。有没有比我提出的更简单的AWK或sed解决方案?

解决方案:


这可以在
sed
中使用保留空间完成:

$ txr -c '@line1
@line2
@line3
@line4
@(data rest)
@(output)
@line1
@line2 @line4
@line3
@  (repeat)
@  rest
@  (end)
@(end)' file
aaa bbb ccc
ddd eee mmm
jjj kkk lll
nnn ooo ppp
  • 2{…}
    在第二行运行所附命令
  • N;HN
    将下两行读入模式空间,握住前两行
  • s/\n.*\n/
    用空格代替中间行
  • p;GD
    打印粘贴的行,加载保留空间,然后删除 第一行(保留前一个替换项删除的行)
或者使用捕获(
\(…\)
)和反向引用(
\1
\2
等):

  • 2{…}
    在第二行运行所附命令
  • N;N
    将下两行读入图案空间
  • s/\(\n.*\)\n\(.*\)/\2\1/
    交换第三行和第四行,连接第一行和第三行。
    • \(\n.*)
      捕获第三行,包括前导换行符
    • \n\(.*)
      捕获第四行,不包括前导换行符
    • /\2\1/
      将匹配的部分(第三行和第四行)替换为空格,然后是第二行,然后是第一个捕获组

这符合经修订的问题陈述书的要求-它打印第1行,在第2行内容后添加第4行作为第2行,然后打印第3行,然后打印第5行及以上内容:

sed '2{N;N;s/\(\n.*\)\n\(.*\)/ \2\1/;}' file
它比问题中的代码简单,因为它只扫描文件一次

输出:

awk 'NR == 1 || NR >= 5 { print; next }
     NR == 2 { save2 = $0 }
     NR == 3 { save3 = $0 }
     NR == 4 { print save2, $0; print save3 }' file
这更简单:

aaa bbb ccc
ddd eee mmm
jjj kkk lll
nnn ooo ppp

其他解决方案可能更快或使用更少的内存,但它们不会更简单。

您如何知道何时需要
mmm
行?你怎么知道它什么时候会出现?您是否试图确保每行上出现的字数相同?单词的数量总是三个吗?如果该行包含
mmmzzz
而不是仅包含
mmm
,会发生什么情况?如果有几行末尾有
ttt
uuu
,该怎么办?是否应该有
ddd eee ttt
mmm zzz uuu
?等到目前为止,这个问题还不够具体,因此无法合理地回答。第二个版本非常好。我有GNU sed,所以这是有效的:sed-r'2{N;N;s/(\N.*)\N(.*)/\2\1/;}文件你不会真的认为这比你开始使用的脚本简单吧???记住你要求的是更简单,而不是更简洁。单词
simpler
很有趣。我不觉得这比两次解析文件更简单(是的,效率更高,但不简单),而且我发现这个过程要复杂得多。我猜
simpler
在旁观者的眼里……问题陈述使得大多数关于解决方案优点的讨论变得无关紧要。这是一组糟糕的(奇怪的,完全不通用的)需求。这可能是一个过度简化的问题(MCVE太多)。正如你所说,旁观者眼中只有简单。您的解决方案更紧凑;我不觉得它更简单。我同意,规定得很差的要求,我理解,旁观者之眼。对我来说,当你要求代码“简单”时,必须考虑到维护的简易性,因为如果你再也不去看它,谁会在乎它是多么的简单。在这种情况下,如果将来我们不使用第2行和第4行,而是将第20行和第40行合并,该怎么办。对于OP最初发布的2-pass解决方案和我发布的修改版本,您只需将数字2更改为20,将数字4更改为40,而对于您和sed解决方案,则需要添加大量代码或进行重写。
awk 'NR == 1 || NR >= 5 { print; next }
     NR == 2 { save2 = $0 }
     NR == 3 { save3 = $0 }
     NR == 4 { print save2, $0; print save3 }' file
aaa bbb ccc
ddd eee mmm
jjj kkk lll
nnn ooo ppp
$ awk 'FNR==NR {if (NR==4) foo=$0; next} FNR==2{$0=$0" "foo} FNR!=4' file file
aaa bbb ccc
ddd eee mmm
jjj kkk lll
nnn ooo ppp