sed“e”和“g”标志不能一起工作

sed“e”和“g”标志不能一起工作

鉴于这种:

echo AAA | sed -r 's/A/echo B/ge'

我明白了:

Becho Becho B

我本以为我会得到“BBB”。这是 GNU sed 版本 4.2.1 的情况。发生了什么事,如何使用执行标志,并且可以在一行上进行多个替换(来自 shell,而不是来自 perl 等)?

答案1

这些标志以与您期望的相反的方式一起工作。这的文档/e, 作为记录:

该命令允许将 shell 命令的输入通过管道传送到模式空间。如果进行了替换,则执行在模式空间中找到的命令,并用其输出替换模式空间。尾随换行符被抑制;如果要执行的命令包含 null 字符,则结果未定义。这是一个 GNU sed 扩展。

写得有点曲折。这意味着,在完成s///该行的命令后,如果发生更改,则(新)行将作为命令执行,其输出将用作该行的替换。

所以对于你给定的命令:

echo AAA | sed -r 's/A/echo B/ge'

它首先将每个替换Aecho B, 和然后将结果作为命令执行。它(粗略地说)与以下效果相同:

echo AAA | sed -r 's/A/echo B/g' | sh

GNUsed不直接支持您想要的模式,尽管您可以根据需要使用更复杂的脚本来伪造它。或者,Perl/e对其s命令的修饰符确实具有您正在寻找的行为,但使用 Perl 表达式代替。

答案2

获得多次替换,但不会获得多次执行。一旦完成所有替换,就会执行该模式。

没有e标志的结果

echo AAA | sed -r 's/A/echo B/g'

echo Becho Becho B

这就是如果您执行的命令行包含e标志,相当于

echo 'Becho Becho B'

答案3

要使用 GNU sed 的 's' 命令和 'e' 标志从 'AAA' 获取 'BBB',可以这样做:

echo AAA | sed -re 's/A/echo -n B;/ge'

“AAA”被替换为“echo -n B;echo -n B;” echo -n B;',最终执行时,会导致 3 个连续运行的 echo 命令,每个命令对应一个全局匹配。 '-n' 省略了 echo 输出中的换行符,使 'B' 最终在一行上(但 sed 在最终打印模式空间时自行附加一个换行符)。

答案4

一些东西:

(1) 您描述的确切用例可以通过以下方式处理

echo AAA | sed 's/A/B/g'

(2) 对于执行,如果这正是您想要的(为了比仅仅回显更高级的用法),您可以使用该e标志作为最后一步:

echo AAA | sed -r 's/A/B/g;s/(.*)/echo \1/e'

(3) 如果您只想在第一个替代命令替换了某些内容时才执行该命令,请使用分支:

echo AAA | sed -r 's/A/B/g;te;b;:e;s/(.*)/echo \1/e'

sed正如上面所写,这些仅适用于 GNU 。 BSD sed(至少是我拥有的版本)不支持该-r选项,并且需要字符串结尾来跟随分支名称。 (您可以通过添加带有参数的多个选项来解决最后一点-e。)

请注意,对于给定的输入 (AAA),这三个单行代码在功能上都是相同的。但如果echo命令更改为其他内容,或者选项-n传递给sed,您就会看到差异。

相关内容