将以反斜杠结尾的行与下一行 awk 连接起来(来自 Famous awk one-liners explained)

Join a line ending with a backslash with the next line awk (from Famous awk one-liners explained)

本练习来自AWK one-liners explained blog post by Peteris Krumins

基本上是这一行

 awk '/\$/ { sub(/\$/,""); getline t; print [=10=] t; next }; 1'

将以反斜杠结尾的每一行与下一行连接起来:

例如输入

12345\
6789
523435\
00000

输出

123456789
52343500000

博客 post 说: 不幸的是,这个衬里无法连接超过 2 行(这留作 reader 的练习,以提出一个连接任意数量的以反斜杠结尾的行的衬里 :))。

因此,使用上面的 AWK 单行代码,如果您使用一个包含 2 行或更多行且末尾有反斜杠的输入文件 (input2),则会给出错误的答案 (output2) 例如输入2

12345\
6789\
523435\
00000

输出 2 - 不正确

123456789\
52343500000

我认为,根据 post,输出应该改为 output3:

输出 3 - 正确

12345678952343500000

如何解决这个问题(输入为 input2 并得到 output3)?

尝试以下操作:

awk '/\$/ { printf "%s", substr([=10=], 1, length([=10=])-1); next } 1' <<'EOF'
12345\
6789\
523435\
00000
EOF

产生

12345678952343500000

这表明 3 连续(或更多)行延续工作正常,与问题中的命令不同。

命令解释:

  • /\$/ 匹配一行末尾 ($) 的 \,表示行继续。
  • substr([=16=], 1, length([=16=])-1) 从输入行 [=18=].
  • 中删除尾随 \
  • 通过使用 printf "%s",(修改后的)当前行打印时没有尾随换行符,这意味着接下来出现的任何打印命令都将直接附加到它后面,有效地将当前行和下一行连接起来。
  • next 完成当前行的处理。
  • 1 是一个常见的 awk 习语,它是 shorthand for { print },即,用于简单地打印输入行(尾随 \n ).

至于为什么原来的命令不起作用

awk '/\$/ { sub(/\$/,""); getline t; print [=12=] t; next }; 1
  • 遇到行继续符(\ 在当前行的末尾),getline t 从文件中读取 next 行并在 current 行之后 按原样 打印它。
  • next 然后完成对当前和 - 由于 getline 调用 - next 行的处理,以便下一个脚本循环处理afternext 行(当前行的 2 行)。
  • 因此,由于通过 getline 读取的行是盲目打印的并且未以任何方式检查,因此在行继续字符处理方面 跳过了

一般来说,正如 Ed Morton 在评论中指出的那样,使用 getline 很少是正确的解决方案,并且可能导致细微的错误 - 请参阅 http://awk.info/?tip/getline.