det*_*tly 346 sed shell-script quoting
执行以下脚本:
#!/bin/sh
sed 's/(127\.0\.1\.1)\s/\1/' [some file]
Run Code Online (Sandbox Code Playgroud)
如果我尝试在sh( dashhere) 中运行它,它会因为需要转义的括号而失败。但是,我并不需要转义反斜线本身(八位位组之间,或\s或\1)。这里的规则是什么?当我需要使用{...}或 时[...]呢?有没有我做什么和不需要逃避的清单?
Gil*_*il' 393
这里有两个级别的解释:shell 和 sed。
在 shell 中,单引号之间的所有内容都按字面解释,单引号本身除外。您可以通过编写'\''(关闭单引号,一个文字单引号,打开单引号)有效地在单引号之间使用单引号。
Sed 使用基本的正则表达式。在 BRE 中,为了按字面处理它们,$.*[\^需要在字符前面加上反斜杠来引用字符,除了在字符集 ( […]) 中。字母、数字和(){}+?|不能被引用(在某些实现中你可以避免引用其中的一些)。序列\(、\)、\n和在某些实现\{中\}、\+、\?、\|和其他反斜杠+字母数字具有特殊含义。$^在某些实现中,您可以避免在某些位置引用。
此外,/如果要出现在方括号表达式之外的正则表达式中,则在此之前需要一个反斜杠。您可以选择一个替代字符作为分隔符,例如,s~/dir~/replacement~或\~/dir~p;如果要将其包含在 BRE 中,则在分隔符之前需要一个反斜杠。如果您选择一个在 BRE 中具有特殊含义的字符并且您想按字面意思包含它,则需要三个反斜杠;我不推荐这样做,因为它在某些实现中的行为可能不同。
简而言之,对于sed 's/…/…/':
'\''在正则表达式中以单引号结尾。$.*/[\]^这些字符之前加上反斜杠(但不在括号表达式内)。(从技术上讲,你不应该在前面加上反斜杠,]但我不知道在括号表达式之外处理]和\]不同的实现。)-要按字面意思处理,请确保它是第一个或最后一个([abc-]或[-abc],不是[a-bc]^要按字面意思处理,请确保它不是第一个(使用[abc^],而不是[^abc]]在由括号表达式匹配的字符列表中,请将其^设为第一个字符(或否定集合的第一个字符):[]abc]或[^]abc](非[abc]]或[abc\]]在替换文本中:
&并且\需要通过在它们前面加上反斜杠来引用,分隔符(通常是/)和换行符也是如此。\后跟一个数字有特殊含义。\后跟字母在某些实现中具有特殊含义(特殊字符),\后跟一些其他字符意味着\c或c取决于实现。sed 's/…/…/')周围使用单引号,用于'\''在替换文本中放置单引号。如果正则表达式或替换文本来自 shell 变量,请记住
\n(除非您有其他sed代码将换行符添加到模式空间,否则永远不会匹配)。但请注意,它在某些sed实现的括号表达式中不起作用。&,\和换行符。sed -e "s/$BRE/$REPL/".R P*_*rin 51
您遇到的问题不是由于 shell 插值和转义 - 这是因为您试图使用扩展的正则表达式语法而不传递 sed-r或--regexp-extended选项。
将您的 sed 行从
sed 's/(127\.0\.1\.1)\s/\1/' [some file]
Run Code Online (Sandbox Code Playgroud)
到
sed -r 's/(127\.0\.1\.1)\s/\1/' [some file]
Run Code Online (Sandbox Code Playgroud)
我相信它会按你的意愿工作。
默认情况下 sed 使用基本的正则表达式(想想 grep 风格),这需要以下语法:
sed 's/\(127\.0\.1\.1\)[ \t]/\1/' [some file]
Run Code Online (Sandbox Code Playgroud)
Kyl*_*nes 20
除非您想将 shell 变量插入到 sed 表达式中,否则请对整个表达式使用单引号,因为它们会导致它们之间的所有内容都按原样解释,包括反斜杠。
因此,如果您希望 sed 看到s/\(127\.0\.1\.1\)\s/\1/在它周围加上单引号,并且 shell 不会触及其中的括号或反斜杠。如果您需要插入一个 shell 变量,只需将该部分放在双引号中。例如
sed 's/\(127\.0\.1\.1\)/'"$ip"'/'
Run Code Online (Sandbox Code Playgroud)
这将为您省去记住哪些 shell 元字符没有被双引号转义的麻烦。