有没有办法让 sed 不等待完整的行?

有没有办法让 sed 不等待完整的行?

sed似乎逐行处理输入。这通常不是问题,但如果行数非常长,则可能会遇到问题。例如,以下命令不会输出任何内容:

{ while :; do echo -n a; done } | sed "s/a/b/"

简单来说,似乎只要收到一个字符就可以输出一些东西(至少在这个模式下)。我试过了sed -u,但什么也没改变。

答案1

来自sed 常见问题解答

Sed 的工作方式如下:sed 每次读取一行,删除终止换行符,将剩余的内容放入模式空间,以便 sed 脚本可以对其进行寻址或更改......

因此,sed在输入中出现换行符之前,实际上并不会查看您的数据。

在您的简单情况下,简单tr 'a' 'b'将有效地取代 sed

否则,也许在输入中添加 LF,并在sed输出中删除它们

答案2

它必须是 的某种特殊实现sed。我不认为存在这样的实现。

推理:

  • POSIX 规范sed明确指出“输入文件应为文本文件”。文本文件由“不包含 NUL 字符,且{LINE_MAX}长度不能超过字节(包括换行符)”的行组成。{LINE_MAX}大于或等于,{_POSIX2_LINE_MAX}后者为2048关联因此,排队时间过长的问题属于“正常”现象(比较)。
  • sed不采用模式,而是采用脚本。它在执行脚本之前将一行读入模式空间,然后执行,然后打印(更改后的)模式空间并读取下一行。

    在您的情况下,不是“至少应该使用这种模式”而是“至少使用这个脚本”。该工具应该分析整个脚本并决定是否应该(或可以)更改其基于行的行为。一些简单的脚本(如您的脚本)可能在理论上允许这样做。像您的模式这样的模式可能有效,但即使是稍微复杂一点的模式也会出现问题。示例:

    代码s/a.*b/c/片段.*是贪婪的。输入流的长度不受限制。如何找到最后一个b

    我的观点是,可以安全地对一些简单的脚本、一些简单的模式进行行为更改。如果更复杂的脚本/模式在理论上符合条件,并且您想利用这一事实,那么分析逻辑就必须更复杂。如果输入结果为 POSIX 文本(请注意事先sed不知道这一点),那么这种“优化”就无关紧要了。

    如果sed支持您想要的功能,则每次都需要做额外的工作;并且需要维护负责替代行为的额外代码。所有这些都是为了满足少数罕见需求。解决方案是允许以可选方式启用此额外功能的选项。


有一个工具可以做你想做的事,至少当脚本足够简单时。它是bbebbeDebian 中的软件包)。如果您在 sed 中的搜索和替换是全局的(s/a/b/g),那么您可以按如下方式进行:

{ while :; do echo -n a; done } | bbe -e 's/a/b/'
# output may not appear immediately, but it will

我的测试表明,该工具始终将其视为s/foo/bar/全局的。

为了避免这种情况,您需要指定要处理的数据块(请参阅man 1 bbe)。以下变体将处理从输入流开头到第一次出现的块a(剩余字节将不改变地通过;如果未找到这样的块,则整个流将不改变地通过):

bbe -b '0:/a/' -e 's/a/b/'

这样最多a会有一个被替换b全部的溪流。

当你需要bbe替换a每行中的第一个时,即模拟 sed 的s/a/b/,可能行很长或者最后一行永不结束,这时就会变得很棘手。诀窍是定义以换行符开头并以 结尾的块a。任何不在任何块内的内容都不会被更改。此命令:

bbe -b '/\n/:/a/' -e 's/a/b/'

只会替换a每行中的第一个,但会替换第一行(因为第一行前面没有换行符,所以它不能属于块)。要解决这个问题,您需要添加一个额外的换行符,稍后再将其删除。

最后一行“永不结束”的多行输入处理示例:

{ echo     # extra newline, it will be removed by tail later
  echo "Actual input starts with capital A."
  echo "Note there are multiple 'a' characters in this line."
  # "neverending" line generator below
  while :; do echo -n a; done
} | bbe -b '/\n/:/a/' -e 's/a/b/' | tail -c +2
# output may not appear immediately, but it will

输出:

Actubl input starts with capital A.
Note there bre multiple 'a' characters in this line.
baaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa…

笔记:

  • bbe似乎不存在对正则表达式的支持(?)。
  • bbe适用于字节,sed适用于字符(通常是多字节字符)。

相关内容