在 GNU sed 中内部处理奇数行 - 我的解决方案是否利用了错误?

Internally handling odd number of lines in GNU sed - is my solution exploiting a bug?

我有一系列的标记,例如

Filename
URL
Filename
URL
...

我想将它们分组到同一行,然后颠倒令牌顺序,所以我做到了

$ echo -e 'Filename\nURL\nFilename\nURL' | sed 'N;s/\(.*\)\n\(.*\)/ /'
URL Filename
URL Filename

我没有问题。

然而,sed 中的 N 运算符非常脆弱,所以我想确保像...

这样不稳定的输入
$ echo -e 'Filename\nURL\nFilename' | sed 'N;s/\(.*\)\n\(.*\)/ /'
URL Filename
Filename

...不会毁掉一切。但我想把它保留在一个单行本中,如果可以的话,尝试使用 sed 内置函数。

无意间发现:

$ echo -e 'hi\nabc\ndef\nghi' | sed '$q1;N;s/\n/ | /' && echo -n even || echo -n odd; echo ' number of input lines'
hi | abc
def | ghi
even number of input lines

$ echo -e 'hi\nabc\ndef' | sed '$q1;N;s/\n/ | /' && echo -n even || echo -n odd; echo ' number of input lines'
hi | abc
def
odd number of input lines

似乎 $ 运算符不会报告 EOF 如果 N 立即修改行。

我猜这是一个错误,我不应该依赖它...?

sed命令按顺序匹配。这就是关键。

假设输入文件如下:

URL 1
Filename 1
URL 2
Filename 2

sed 处理文件时发生的事情是 sed 读取第一行,将其与 $ 匹配(失败)然后 运行s Ns 命令。

然后读取 "next" 行(现在是第三行,URL 2 行)与 $ 匹配(失败),然后 运行s Ns 命令。此时 sed 然后尝试通过输入读取下一行以准备下一个 运行 只有没有更多的输入所以它退出。

现在假设输入文件为

URL 1
Filename 1
Filename 2

sed 首先读取第一行,将其与 $ 匹配(失败),然后执行 Ns 命令。然后它读取 "next" 行(再次是第三行,这次是 Filename 2 行)并将其与 $ 匹配( 成功 ),然后退出。

如果您有一个 $ 地址命令 之后 N 命令将在偶数行的文件上触发(如 [=当该命令为 运行ning 时,13=] 现在将位于最后一行。

示例:

$ printf %s\n "U 1" "F 1" "U 2" "F 2" | sed '$q1;N;s/\n/ | /;$s/$/ - last line/' && echo even || echo odd
U 1 | F 1
U 2 | F 2 - last line
even
$ printf %s\n "U 1" "F 1" "F 2" | sed '$q1;N;s/\n/ | /;$s/$/ - last line/' && echo even || echo odd
U 1 | F 1
F 2
odd