sed 中第一个附加换行符需要额外的反斜杠

sed 中第一个附加换行符需要额外的反斜杠

在匹配模式后附加一些文本时,我想添加一个带有注释的空行,以将我的添加与其余内容隔离。但是,我注意到,对于第一个\n,我需要使用\附加的\(make it \\n) 来转义,但这显然对于其余附加文本来说不是必需的。为什么会这样呢?

我在 SUSE 11 服务器(bash v3.2.57(2) 和 GNU sed 版本 4.1.5)上生成的示例是:

edwdev@hdpedge1:/edw> sed '/test/a \\nNot a test\nJust Playing' <<< test
test

Not a test
Just Playing

如果我不转义第一个\n(在ased 命令之后,我会得到一个n打印而不是换行。

edwdev@hdpedge1:/edw> sed '/test/a \nNot a test\nJust Playing' <<< test
test
nNot a test
Just Playing

请注意,我故意在命令后添加了一个空格,a这样它就不会意外地与备用语法发生冲突。

\n如果我替换为 ,则会观察到相同的行为\t。命令后的空格数a似乎并不重要;即使在多个空格之后,也需要转义第一个反斜杠才能打印特殊字符。


在我最初观察到的另一个环境中,情况也是如此;Centos 7 x64 VM,bash 版本是 4.2.46(2),sed 版本是 GNU sed 4.2.2

sed -i '/\[mysqld\]/a \\n# <<INSERTED MANUALLY>>\ntransaction-isolation=READ-COMMITTED\ninnodb_flush_method=O_DIRECT\nmax_connections=550\n# <<END OF MANUAL INSERTIONS >>\n' /etc/my.cnf

输出:

...
[mysqld]

# <<INSERTED MANUALLY>>
transaction-isolation=READ-COMMITTED
innodb_flush_method=O_DIRECT
max_connections=550
# <<END OF MANUAL INSERTIONS >>

...

首先不转义输出\n:

[mysqld]
n# <<INSERTED MANUALLY>>
transaction-isolation=READ-COMMITTED
innodb_flush_method=O_DIRECT
max_connections=550
# <<END OF MANUAL INSERTIONS >>

这种行为有什么特殊原因吗?我在浏览文档时无法找到任何详细信息(这里),诚然,我还没有彻底阅读整个文档。

答案1

标准a命令的形式sed

a\
text to be appended

c和命令i遵循相同的格式。

如果要附加更多行,则必须对每行的换行符进行转义:

a\
text to\
be appended

标准sed不知道\n像 GNU 那样解释为换行符sed,因此使用非 GNU 的单行命令sed将被写bash为(在 中):

sed $'/test/a\\\n\\\nNot a test\\\nJust Playing\n' <<<test

在这里,我们使用$'...'shell 将每个内容替换\n为实际的换行符\\\.

该命令可以写成以下形式,但不具有$'...'以下功能bash

sed '/test/a\
\
Not a test\
Just Playing
' <<<test

这两个命令也适用于 GNU sed

GNUsed另外允许出现附加文本,而无需在其与前面的之间插入换行符a,并且允许\完全删除,\但会将紧跟在命令后面的命令解释为命令a标准形式中的反斜杠a\(这是你问题中的基本问题)。 GNUsed还在脚本中附加文本的末尾添加换行符。所以使用 GNU sed,你可以写

sed '/test/a\ \
Not a test\
Just Playing' <<<test

sed或者,利用 GNU知道的事实\n

sed '/test/a\\nNot a test\nJust Playing' <<<test

答案2

这并不是完全记录的行为,但整个事情都是一个扩展。类似扩展的所有三个命令(aic)的行为方式相同:忽略前导空格,如果文本以 开头\,则将其丢弃。本质上,sed 使用以下哪种形式并不重要:

i foo
i \foo
i \
foo

它们都是相同的。 (我知道我i在这里使用过,但请检查 的描述ai并且c- 这是超现实的。)

代码显示如下:

1111         case 'a':
1112         case 'i':
1113         case 'c':
1114           ch = in_nonblank ();
1115 
1116         read_text_to_slash:
1117           if (ch == EOF)
1118             bad_prog (_(EXPECTED_SLASH));
1119 
1120           if (ch == '\\')
1121             ch = inchar ();

相关内容