为什么备用分隔符不能与sed-e'/模式/s/a/b/';?
我发现了一些没有意义的东西为什么备用分隔符不能与sed-e'/模式/s/a/b/';?,sed,perl,Sed,Perl,我发现了一些没有意义的东西 cat config.h的输出: define somevar foo // Sample variable 此版本的命令用于将foo更改为bar并保留注释: sed -e '/somevar/s/foo/bar/' config.h 这不起作用: sed -e '|somevar|s|foo|bar|' config.h 给出此错误: sed:-e表达式#1,字符1:未知命令:` |' 有趣的是,这确实有效: sed -e '/somevar/s|foo|ba
cat config.h的输出
:
define somevar foo // Sample variable
此版本的命令用于将foo更改为bar并保留注释:
sed -e '/somevar/s/foo/bar/' config.h
这不起作用:
sed -e '|somevar|s|foo|bar|' config.h
给出此错误:
sed:-e表达式#1,字符1:未知命令:` |'
有趣的是,这确实有效:
sed -e '/somevar/s|foo|bar|' config.h
也许我遗漏了一些文档。在同一个sed命令中使用两个不同的分隔符似乎很奇怪
Bug还是功能?我投票支持功能
它们是两个不同的命令,搜索命令和替换命令。据我所知,它只允许更改替换命令的分隔符
中国的情况也类似。可以使用/…/
执行正则表达式搜索,但如果要更改分隔符,则必须使用m
将其明确标记为搜索,如:m |…|
我想这可能与一些词法分析问题有关,但我不知道原因。允许对
/pattern/
使用不同的分隔符会导致分析歧义
ispaghetti
应该像/spaghett/
那样,还是应该像i spaghetti
那样插入文本
对于s
和y
不存在这种歧义。当您看到这两个字符中的任何一个时,您就知道正在读取的命令,然后可以将下一个字符解释为分隔符
如果我们用一个类似的可识别字符开始它,我们可以解决/pattern/
的这种歧义,而且sed确实有一个单独的地址说明符:反斜杠,如\\\\pattern
(这与转义不同)
因此,我们可以编写\\pattern | s | foo | bar
地址和编辑命令是分开的,因此\$pattern$s\u foo\u bar
和/pattern/s\foo\u bar
也可以工作 这将起作用:
sed -e '\|somevar|s|foo|bar|'
GNU sed的man
页面非常清楚这一点:
/regexp/
Match lines matching the regular expression regexp.
\cregexpc
Match lines matching the regular expression regexp. The c may
be any character.
也就是说,c
可以是任何字符,但开头的\
是必需的
我周围没有免费的BSD,但根据man
页面,也有非常清楚的:
除非是斜杠,否则开头分隔符前面必须加反斜杠
另一方面,在OSX中,这一点根本不清楚:
In a context address, any character other than a backslash (``\'')
or newline character may be used to delimit the regular expression.
Also, putting a backslash character before the delimiting character
causes the character to be treated literally. For example, in the
context address \xabc\xdefx, the RE delimiter is an ``x'' and the
second ``x'' stands for itself, so that the regular expression is
``abcxdef''.
请注意,这里的示例使用了\xpatternx
,而不仅仅是xpatternx
。这就是它给出的所有线索,它没有明确说明xpatternx
将不起作用
根据的论点,
sed
(以及前面提到的其他语言,如perl
)需要这个额外的线索才能正常工作。您完全可以对匹配的地址使用备用分隔符(/regex/
),但是您需要告诉sed,您打算使用该分隔符进行匹配。执行此操作的方法是使用前导反斜杠\
。因此,您的命令可以是:
sed -e '\|somevar|s|foo|bar|' config.h
或者同样容易:
sed -e '\%somevar%s|foo|bar|' config.h
参考:功能。在
sed -e '/somevar/s/foo/bar/' config.h
/somevar/
是一个地址。地址必须与其他功能区分开来,如y
(yank)、i
(insert)、a
(append)等。通常,sed命令被解析为
[address[,address]]function[arguments]
你说得对,但是sed在这种情况下使用“\”而不是
m
。@bonsaiviking:我不知道。我会在这里感谢你,并将投票表决你的答案,澄清它。它在,而且FreeBSD的手册页更清楚:“除非是斜杠,否则开头分隔符前面必须有反斜杠。”谢谢@bonsaiviking,我可以在Linux上检查它更清楚。我改进了我的答案。很好地讨论了解析歧义,但是如果第一个分隔符前面有反斜杠“\”@bonsaiviking,sed确实提供了这个功能,这是一个很好的观点。