在匹配模式后附加一些文本时,我想添加一个带有注释的空行,以将我的添加与其余内容隔离。但是,我注意到,对于第一个\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
(在a
sed 命令之后,我会得到一个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
这并不是完全记录的行为,但整个事情都是一个扩展。类似扩展的所有三个命令(a
、i
和c
)的行为方式相同:忽略前导空格,如果文本以 开头\
,则将其丢弃。本质上,sed 使用以下哪种形式并不重要:
i foo
i \foo
i \
foo
它们都是相同的。 (我知道我i
在这里使用过,但请检查 的描述a
,i
并且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 ();