采取以下脚本:
#!/bin/sh
sed 's/(127\.0\.1\.1)\s/\1/' [some file]
如果我尝试在sh
(dash
here)中运行此命令,它将由于括号而失败,该括号需要转义。但是,我并不需要转义反斜线本身(八位位组之间,或\s
或\1
)。这是什么规则?那我什么时候需要使用{...}
或[...]
呢?有我要做的和不需要逃避的工作的清单吗?
采取以下脚本:
#!/bin/sh
sed 's/(127\.0\.1\.1)\s/\1/' [some file]
如果我尝试在sh
(dash
here)中运行此命令,它将由于括号而失败,该括号需要转义。但是,我并不需要转义反斜线本身(八位位组之间,或\s
或\1
)。这是什么规则?那我什么时候需要使用{...}
或[...]
呢?有我要做的和不需要逃避的工作的清单吗?
Answers:
这里有两种解释级别:shell和sed。
在外壳程序中,单引号之间的所有内容均按字面意义进行解释,单引号本身除外。通过编写,您可以有效地在单引号之间使用一个单引号'\''
(关闭单引号,一个文字单引号,打开单引号)。
Sed使用基本的正则表达式。在BRE中,为了使它们按字面意义处理$.*[\^
,除内部字符集([…]
)外,必须在它们前面加上一个反斜杠来对字符进行引用。字母,数字和(){}+?|
不能被引用(在某些实现中,您可以引用其中的一些内容)。的序列\(
,\)
,\n
,和在一些实施方式中\{
,\}
,\+
,\?
,\|
和其他反斜杠+字母数字具有特殊的含义。您可以不用$^
在某些实现中的某些位置引用而摆脱困境。
此外,/
如果要在方括号表达式之外的正则表达式中出现反斜杠,则需要先加一个反斜杠。您可以通过写一个或多个其他字符作为分隔符,例如s~/dir~/replacement~
或\~/dir~p
。如果要将其包含在BRE中,则需要在定界符之前加反斜杠。如果您选择在BRE中具有特殊含义的字符,并且想要按字面意义包含它,则需要三个反斜杠;我不建议这样做,因为在某些实现中它的行为可能有所不同。
简而言之,适用于sed 's/…/…/'
:
'\''
在正则表达式中以单引号结尾。$.*/[\]^
仅在那些字符之前(但不在方括号表达式中)放在反斜杠之前。(从技术上讲,您不应该在前面加上反斜杠,]
但我不知道在方括号表达式之外处理]
和\]
有所不同的实现。)-
要按字面意义进行处理,请确保它是第一个或最后一个([abc-]
或[-abc]
,不是[a-bc]
^
使其按字面意义处理,请确保它不是第一个(使用[abc^]
,而不是[^abc]
]
在由方括号表达式匹配的字符列表中,请使其成为第一个字符(或^
对于否定的集合,在第一个字符之后):[]abc]
或[^]abc]
(不是[abc]]
nor[abc\]]
在替换文本中:
&
并且\
需要在它们前面加上反斜杠,以及定界符(通常是/
)和换行符。\
后面跟数字有特殊含义。\
在某些实现中,其后带有字母具有特殊含义(特殊字符),在某些实现中,\
其后带有一些其他字符方式\c
或c
取决于实现。sed 's/…/…/'
)周围加上单引号,可用于'\''
在替换文本中加上单引号。如果正则表达式或替换文本来自shell变量,请记住
\n
(除非您有其他sed
代码向模式空间添加换行符,否则换行符将永远不匹配)。但是请注意,在某些sed
实现中,它将无法在方括号表达式中使用。&
,\
和换行需要被引用。sed -e "s/$BRE/$REPL/"
。\\*
)。示例:echo "***NEW***" | sed /\\*\\*\\*NEW\\*\\*\\*/s/^/#/
您遇到的问题不是由于shell插值和转义引起的-这是因为您尝试使用扩展的正则表达式语法而不传递sed -r
或--regexp-extended
选项。
更改您的sed行
sed 's/(127\.0\.1\.1)\s/\1/' [some file]
至
sed -r 's/(127\.0\.1\.1)\s/\1/' [some file]
它将如您所愿地工作。
缺省情况下,sed使用基本正则表达式(例如grep样式),它将需要以下语法:
sed 's/\(127\.0\.1\.1\)[ \t]/\1/' [some file]
-r
在我的情况下,必须添加一个选项。
除非您想将shell变量插入sed表达式中,否则请对整个表达式使用单引号,因为它们会使它们之间的所有内容都按原样解释,包括反斜杠。
因此,如果您希望sed看到s/\(127\.0\.1\.1\)\s/\1/
单引号引起来,并且外壳不会碰到其中的括号或反斜杠。如果您需要对shell变量进行插值,则仅将该部分放在双引号中。例如
sed 's/\(127\.0\.1\.1\)/'"$ip"'/'
这样可以避免记住双引号不能转义哪些外壳元字符的麻烦。
sed
看看s/(127\.0\.1\.1)/...
,但是按原样将其放在shell脚本中是行不通的。您在说外壳没有碰到括号似乎是错误的。我已经对问题进行了详细编辑。
sed 's/(127\.0\.1\.1)/IP \1/'
失败,因为sed需要查看\(
和\)
语法,而不是(
和)
。
function sedPath { path=$((echo $1|sed -r 's/([\$\.\*\/\[\\^])/\\\1/g'|sed 's/[]]/\[]]/g')>&1) } #Escape path for use with sed