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
支持您想要的功能,则每次都需要做额外的工作;并且需要维护负责替代行为的额外代码。所有这些都是为了满足少数罕见需求。解决方案是允许以可选方式启用此额外功能的选项。
有一个工具可以做你想做的事,至少当脚本足够简单时。它是bbe
(bbe
Debian 中的软件包)。如果您在 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
适用于字符(通常是多字节字符)。