请采用以下脚本:

#!/bin/sh
sed 's/(127\.0\.1\.1)\s//' [some file]


如果我尝试在sh(此处为dash)中运行此脚本,则由于括号的原因,它将失败,需要将其转义。但是我不需要自己转义反斜杠(在八位位组之间,或在\s中)。这是什么规则?当我需要使用{...}[...]怎么办?是否有我需要做的列表和不需要逃避的列表?

评论

这是一个bash函数,用于转换与SED一起使用的路径:function sedPath {path = $((echo $ 1 | sed -r's /([\ $ \。\ * \ / \ [\\ ^])/ \\ \ 1 / g'| sed's / []] / \ []] / g')>&1)}#与sed一起使用的转义路径

另请参阅:需要在Bash中转义哪些字符?我们怎么知道?

dura lex,sed sed

#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/…/…/'代码将换行符添加到模式空间,否则换行符将永远不匹配)。但是请注意,在某些'\''实现中,它将无法在方括号表达式中使用。
在替换文本中,需要对\nsed和换行符进行引用。表达式)。
对插值使用双引号: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。

总结起来,版本的差异实际上可以决定正确的语法是什么样,或者必须转义哪些字符。我希望这可以为最初的问题和接受的答案提供更多的背景信息,并帮助其他人根据脚本和命令用法的最终目标来考虑应如何进行。