前言:
来看这个内容的,估计和我一样被绕晕了, 找不到规则。其实这是shell比较灵活导致的。
其实遵循如下原则可以避免莫名其妙的意外(少掉头发)。
1) 坚决不使用反引号(`), 坚决使用$()
2) 对于不需要转义的字符串,坚决使用单引号括起来。 (反斜杆, 在双引号, 或不加引号的情况下, 会有特殊的变化)
例如:
/opt/syb/test # echo \opt\tmp\ | sed 's:\\:\\\\:g'
opttmp
echo "\opt\tmp\" | sed 's:\\:\\\\:g'
> ^C
惊不惊喜意不意外???!!!
推荐做法:
echo '\opt' | sed 's:\\:\\\\:g'
也可以用双引号:
echo '\opt' | sed "s:\\\\:\\\\\\\\:g"
转义列表:
https://www.cnblogs.com/fnlingnzb-learner/p/6839669.html
https://www.cnblogs.com/f-ck-need-u/p/7499309.html
于是,关于sed如何和shell交互的问题可以得出一套结论:
- 遇到需要被shell解析的都不加引号,或者加双引号;
- 遇到shell和所执行命令共有的特殊字符时,要想被sed解析,必须加单引号,或者在双引号在加反斜线转义;
- 那些无关紧要的字符,无论加什么引号。
总结:
不管是用单引号,还是双引号。
针对\匹配替换: 需要转义 \\
针对/匹配替换, 使用:作为分隔符, 不用转义
https://unix.stackexchange.com/questions/379572/escaping-both-forward-slash-and-back-slash-with-sed
You need to escape (with backslash \
) all substituted slashes /
and all backslashes \
separately, so:
$ echo "/tmp/test/folder1/test.txt" | sed 's/\//\\\//g'
\/tmp\/test\/folder1\/test.txt
but that's rather unreadable.
However, sed
allows to use almost any character as a separator instead of /
, this is especially useful when one wants to substitute slash /
itself, as in your case, so using for example semicolon ;
as separator the command would become simpler:
echo "/tmp/test/folder1/test.txt" | sed 's;/;\\/;g'
Other cases:
-
If one wants to stick with slash as a separator and use double quotes then all escaped backslashes have to be escaped one more time to preserve their literal values:
echo "/tmp/test/folder1/test.txt" | sed "s/\//\\\\\//g"
-
if one doesn't want quotes at all then yet another backslash is needed:
echo "/tmp/test/folder1/test.txt" | sed s/\\//\\\\\\//g
$ sed 's:/:\\/:g' <<<"$str"
\/tmp\/test\/folder1\/test.txt
https://unix.stackexchange.com/questions/398646/why-is-a-single-backslash-shown-when-using-quotes.
the backslash retains its special meaning only when followed by one of the following characters: ‘$
’, ‘`
’, ‘"
’, ‘\
’, or newline
. Within double quotes, backslashes that are followed by one of these characters are removed.
5
Backslash is interpreted differently according context:
-
Within double quotes (your first example):
The backslash retains its special meaning only when followed by one of the following characters: $, `, ", \, or <newline>.
-
Without quotes (your second example):
A non-quoted backslash (\) is the escape character. It preserves the literal value of the next character that follows, with the exception of <newline>. If a \<newline> pair appears, and the backslash is not itself quoted, the \<newline> is treated as a line continuation (that is, it is removed from the input stream and effectively ignored).
-
Using the construct
$'....'
, where you can use inside the quote the standard backspace character, nearly as in C. e.g.\n
,\t
, etc. -
Using backquotes:
-
When the old-style backquote form of substitution is used, backslash retains its literal meaning except when followed by $, `, or \.