我发现这是没有意义的事情。
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 expression#1,char 1:unknown命令:`|'
有趣的是,这确实有效:
sed -e '/somevar/s|foo|bar|' config.h
也许我错过了文档的某些部分。在同一个sed命令中有两个不同的分隔符似乎很奇怪。
错误或功能?
答案 0 :(得分:31)
这将有效:
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
可以是任何字符,但起始\
是强制性的。
我没有FreeBSD,但根据@bonsaiviking 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
不起作用。
根据@that-other-guy的论点,sed
(以及perl
等{{1}}指出的其他语言)需要这条额外的线索才能正常工作。
答案 1 :(得分:8)
为/pattern/
允许不同的分隔符会引入解析模糊性。
ispaghetti
应该是/spaghett/
,还是应该插入像i spaghetti
这样的文字?
s
和y
没有这种歧义。当您看到其中任何一个字符时,您知道正在阅读的命令,然后您可以将下一个字符解释为分隔符。
如果我们用类似的可识别字符开始它,我们可以解决/pattern/
的这种歧义,并且sed确实有一个单独的地址说明符:反斜杠,如\|pattern|
(这是不一样的逃避)。
因此我们可以写\|pattern|s|foo|bar|
。
地址和编辑命令是分开的,因此\$pattern$s_foo_bar_
和/pattern/s#foo#bar#
也可以使用。
答案 2 :(得分:6)
您绝对可以使用备用分隔符作为匹配地址(/regex/
),但您需要告诉sed
您打算与该分隔符进行匹配。这样做的方法是使用前导反斜杠\
。所以你的命令可以是:
sed -e '\|somevar|s|foo|bar|' config.h
或同样容易:
sed -e '\%somevar%s|foo|bar|' config.h
答案 3 :(得分:3)
我的投票是功能。
它们是两个不同的命令,搜索一个/.../
和替换一个s/.../.../
。据我所知,只允许更改替换命令的分隔符。
在perl中类似。您可以使用/.../
进行正则表达式搜索,但如果要更改分隔符,则必须明确将其标记为m
的搜索,例如:m|...|
。
我想这会与一些词法解析问题有关,但我不知道原因。
答案 4 :(得分:2)
特征。在
sed -e '/somevar/s/foo/bar/' config.h
/somevar/
是地址。地址必须与其他函数区分开来,例如y
(yank),i
(插入),a
(追加)等等。通常,sed命令被解析为
[address[,address]]function[arguments]