#!/bin/sh
sed 's/(127\.0\.1\.1)\s//' [some file]
如果我尝试在
sh
(此处为dash
)中运行此脚本,则由于括号的原因,它将失败,需要将其转义。但是我不需要自己转义反斜杠(在八位位组之间,或在\s
或
中)。这是什么规则?当我需要使用{...}
或[...]
怎么办?是否有我需要做的列表和不需要逃避的列表?#1 楼
此处有两种解释级别:shell和sed。在shell中,单引号之间的所有内容均按字面解释,除了单引号本身。通过编写
'\''
(封闭单引号,一个文字单引号,开放单引号),您可以有效地在单引号之间使用单引号。Sed使用基本正则表达式。在BRE中,为了使它们按字面意义处理,除内部字符集(
$.*[\^
)外,需要在字符[…]
前面加上反斜杠来对其进行引用。字母,数字和(){}+?|
一定不能用引号引起来(在某些实现中,您可以引用其中的一些内容)。序列\(
,\)
,\n
以及在某些实现中的\{
,\}
,\+
,\?
,\|
和其他反斜杠+字母数字具有特殊含义。您可以不用在某些实现中的某些位置引用$^
来逃脱。此外,如果要在方括号表达式之外的正则表达式中出现
/
,则需要在其前加反斜杠。您可以通过编写例如s~/dir~/replacement~
或\~/dir~p
来选择其他字符作为分隔符;如果要在定界符中包含反斜杠,则需要在反斜杠之前加反斜杠。如果您选择一个在BRE中具有特殊含义的字符,并且想要按字面意义包含它,则需要三个反斜杠;我不建议这样做,因为它在某些实现中的行为可能会有所不同。概括地说,对于
sed 's/…/…/'
: br />使用'\''
在正则表达式中以单引号结尾。 (从技术上讲,您不应该在$.*/[\]^
之前加反斜杠,但我不知道在方括号表达式之外将]
和]
区别对待的实现。)在方括号表达式内,要对
\]
进行字面处理,请确保它是第一个或最后一个(-
或[abc-]
,而不是[-abc]
)。在方括号表达式内,要对
[a-bc]
进行字面处理,请确保它不是第一个(请使用^
,而不要使用[abc^]
)。要将
[^abc]
包含在由方括号表达式匹配的字符列表中,请使其成为第一个字符(或对于否定集,在]
之后是第一个字符):^
或[]abc]
(而不是[^]abc]
或[abc]]
)。在替换文本中:
[abc\]]
和&
需在其前面加上反斜杠,如使用定界符(通常是
\
)和换行符。/
后跟一个数字具有特殊含义。在某些实现中,\
后跟一个字母具有特殊含义(特殊字符),而在实现中,\
后跟一些其他字符表示\
或\c
(取决于实现)。 如果正则表达式或替换文本来自shell变量,请记住
正则表达式是BRE,而不是
在正则表达式中,换行符需要表示为
c
(除非您有其他sed 's/…/…/'
代码将换行符添加到模式空间,否则换行符将永远不匹配)。但是请注意,在某些'\''
实现中,它将无法在方括号表达式中使用。在替换文本中,需要对
\n
,sed
和换行符进行引用。表达式)。对插值使用双引号:
sed
。评论
转义实际的通配符(*)时,可以使用双反斜杠(\\ *)。示例:echo“ *** NEW ***” | sed / \\ * \\ * \\ * NEW \\ * \\ * \\ * / s / ^ /#/
–danger89
19年3月20日在16:44
“使用'\'结束正则表达式中的单引号。”在macOS Catalina上对我不起作用。我不得不切换到使用双引号并将单引号放入其中。尝试了0-2反斜杠之间的所有内容。
–弗洛里安·温德尔伯恩(Florian Wendelborn)
19/12/13在19:43
#2 楼
您遇到的问题不是由于shell插值和转义引起的-这是因为您尝试使用扩展的正则表达式语法而不传递sed-r
或--regexp-extended
选项。将sed行从
sed 's/(127\.0\.1\.1)\s//' [some file]
到
sed -r 's/(127\.0\.1\.1)\s//' [some file]
,它将按您的预期工作。
默认情况下,sed使用基本正则表达式(认为grep样式),这需要以下语法:
sed 's/\(127\.0\.1\.1\)[ \t]//' [some file]
评论
我又遇到了这个问题,忘了向下滚动以找到上次投票赞成的解决方案。再次感谢。
–isaaclw
2014年4月4日在20:17
非常感谢。在我的情况下,必须添加-r作为选项。
–你好再见
2015年5月21日在8:23
请注意,-r在MacOS上不可用
–Hubert Grzeskowiak
1月31日0:10
@HubertGrzeskowiak在MacOS上使用-E与-r看到的技巧相同
–费利克斯
3月30日8:14
使用#作为分隔符代替引号可能会有所帮助,以减少使用大量引号引起的视觉噪声
–jouell
4月3日,下午2:43
#3 楼
除非您想将shell变量插入sed表达式中,否则请对整个表达式使用单引号,因为它们会使它们之间的所有内容都按原样解释,包括反斜杠。因此,如果要sed请参阅
s/\(127\.0\.1\.1\)\s//
,将单引号引起来,并且外壳不会碰到其中的括号或反斜杠。如果您需要对shell变量进行插值,则仅将该部分放在双引号中。例如,sed 's/\(127\.0\.1\.1\)/'"$ip"'/'
这将使您免于记住哪些外壳元字符没有被双引号引起来的麻烦。
评论
我想让sed查看s /(127 \ .0 \ .1 \ .1)/ ...,但是按原样将其放在shell脚本中是行不通的。您在说外壳没有碰到括号似乎是错误的。我已对问题进行了详细编辑。
–甜蜜地
2012年2月28日在6:14
外壳没有碰到括号。您需要背影,因为sed需要查看它们。 sed的s /(127 \ .0 \ .1 \ .1)/ IP \ 1 /失败,因为sed需要查看\(和\)的组语法,而不是(和)。
–凯尔·琼斯(Kyle Jones)
2012-2-28在6:31
facepalm它不在手册页中,但是在我发现的一些在线手册中。这对正则表达式是否正常,因为我从未在正则表达式库中使用过(例如,在Python中)?
–甜蜜地
2012年2月28日在6:33
对于传统的Unix命令,有基本的正则表达式和扩展的正则表达式。细节。 sed使用基本的正则表达式,因此组语法需要反斜杠。 Perl和Python甚至超出了扩展的正则表达式。当我四处闲逛时,我发现了一个非常有用的图表,该图表说明了当我们轻声地说“正则表达式”时我们会想到的一个令人困惑的难题。
–凯尔·琼斯(Kyle Jones)
2012年2月28日在7:07
我还要补充一点,不能在单引号内使用的唯一字符是单引号。
– Enzotib
2012年2月28日在9:08
#4 楼
我认为值得一提的是,虽然sed基于POSIX标准,该标准仅指定对基本正则表达式(BRE)的支持,但实际上存在sed命令的两个不同版本-BSD(Mac OS)和GNU(Linux发行版) 。每个版本都实现了POSIX标准的相似以及唯一的扩展,并且会影响sed在不同平台上的功能。结果,在一个系统上按预期运行的sed命令的正确语法实际上可能在另一个系统上转换为完全不同的结果。对于转义字符和特殊字符的使用,这可能导致意外的行为。这些对POSIX标准的扩展在sed的GNU版本上趋于普遍,通常常常提供不太严格的格式设置的便利,尤其是与BSD版本相比。但是,尽管GNU sed确实允许某些特殊字符的功能,但它们实际上仍然不符合POSIX。此外,在GNU sed中,基本正则表达式和扩展正则表达式(ERE)之间的唯一真正区别是以下特殊字符的行为:
'?','+',括号,花括号(' {}'和'|'
,尽管如此,但某些特殊字符在BSD sed上的支持有限或根本没有支持,例如'|','?'和' +”,因为它更加符合POSIX语法标准。以类似于GNU sed的方式包含这些字符,通常会导致利用sed的脚本的可移植性和功能性问题。还值得注意的是,POSIX BRE语法没有为某些转义序列定义含义,最值得注意的是:\ |,+,\ ?、`,\,\ <,>,\ b,\ B,\ w和\ W,
对于运行BSD / Mac OS版本sed的用户,模拟某些特殊字符的行为可能会有些棘手,但在大多数情况下可以做到。例如,可以以POSIX兼容的方式模拟+,如下所示:
{1,}和\?如下所示:{0,1}
但是,通常不支持控制字符序列。如果有可能,使用GNU sed当然是最容易的,但是如果您在两个平台上都需要功能,请记住仅使用POSIX功能以确保可移植性。如果您是Mac用户,并且想利用GNU sed而不是BSD sed,则可以尝试安装Homebrew,并通过以下命令通过命令行下载GNU sed:$ brew install gnu-sed。
总结起来,版本的差异实际上可以决定正确的语法是什么样,或者必须转义哪些字符。我希望这可以为最初的问题和接受的答案提供更多的背景信息,并帮助其他人根据脚本和命令用法的最终目标来考虑应如何进行。
评论
这是一个bash函数,用于转换与SED一起使用的路径:function sedPath {path = $((echo $ 1 | sed -r's /([\ $ \。\ * \ / \ [\\ ^])/ \\ \ 1 / g'| sed's / []] / \ []] / g')>&1)}#与sed一起使用的转义路径另请参阅:需要在Bash中转义哪些字符?我们怎么知道?
dura lex,sed sed