我已经厌倦了在使用许多正则表达式实现时,总是试图猜测是否应该转义特殊字符如'()[]{}|
'等。
例如Python、sed、grep、awk、Perl、rename、Apache、find等都不同。是否有规则集可以告诉我何时应该转义特殊字符,何时不应该转义? 是否取决于正则表达式类型,如PCRE、POSIX或扩展正则表达式?
我已经厌倦了在使用许多正则表达式实现时,总是试图猜测是否应该转义特殊字符如'()[]{}|
'等。
例如Python、sed、grep、awk、Perl、rename、Apache、find等都不同。是否有规则集可以告诉我何时应该转义特殊字符,何时不应该转义? 是否取决于正则表达式类型,如PCRE、POSIX或扩展正则表达式?
使用 Raku(前身为 Perl_6)
可行的方法(对于非字母数字字符,除了下划线,需要加上反斜杠或引号):
~$ raku -e 'say $/ if "#.*?" ~~ m/ \# \. \* \? /; #works fine'
「#.*?」
根据Damian Conway的pdf/talk "Everything You Know About Regexes Is Wrong",正则表达式语言有六种不同的风格。Raku是标准Perl(5)/PCRE正则表达式的重要改进(约15年)。
在这15年中,Perl_6 / Raku语言专家决定所有非字母数字字符(除下划线外)都应该被保留为正则表达式元字符,即使没有现有的用法。为了表示非字母数字字符(除下划线外)作为文字,需要使用反斜杠或转义它们。
因此,如果找到与文字#.*?
序列匹配的内容,则上述示例将打印$/
匹配变量。如果不这样做,将会发生以下情况:#
被解释为注释的开始,.
点被解释为任何字符(包括空格),*
星号被解释为零个或多个量词符,?
问号被解释为零个或一个量词符或吝啬(即非贪婪)量词修饰符(取决于上下文):
错误:
~$ ~$ raku -e 'say $/ if "#.*?" ~~ m/ # . * ? /; #ERROR!'
===SORRY!===
Regex not terminated.
at -e:1
------> y $/ if "#.*?" ~~ m/ # . * ? /; #ERROR!⏏<EOL>
Regex not terminated.
at -e:1
------> y $/ if "#.*?" ~~ m/ # . * ? /; #ERROR!⏏<EOL>
Couldn't find terminator / (corresponding / was at line 1)
at -e:1
------> y $/ if "#.*?" ~~ m/ # . * ? /; #ERROR!⏏<EOL>
expecting any of:
/
jot -s '' -c - 32 126 |
mawk '
function ___(__,_) {
return substr(_="",
gsub("[][!-/_\140:-@{-~]","[&]",__),
gsub("["(_="\\\\")"^]",_ "&",__))__
} ($++NF = ___($!_))^_'
!"#$%&'()*+,-./0123456789:;<=>?
@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_
`abcdefghijklmnopqrstuvwxyz{|}~
[!]["][#][$][%][&]['][(][)][*][+][,][-][.][/]
0 1 2 3 4 5 6 7 8 9 [:][;][<][=][>][?]
[@] ABCDEFGHIJKLMNOPQRSTUVWXYZ [[]\\ []]\^ [_]
[`] abcdefghijklmnopqrstuvwxyz [{][|][}][~]
方括号更易处理,因为没有触发“转义过多”的警告信息的风险,例如:
function ____(_) {
return substr("", gsub("[[:punct:]]","\\\\&",_))_
}
\!\"\#\$\%\&\'\(\)\*\+\,\-\.\/ 0123456789\:\;\<\=\>\?
\@ABCDEFGHIJKLMNOPQRSTUVWXYZ\[\\\]\^\_\`abcdefghijklmnopqrstuvwxyz \{\|\}\~
gawk: cmd. line:1: warning: regexp escape sequence `\!' is not a known regexp operator
gawk: cmd. line:1: warning: regexp escape sequence `\"' is not a known regexp operator
gawk: cmd. line:1: warning: regexp escape sequence `\#' is not a known regexp operator
gawk: cmd. line:1: warning: regexp escape sequence `\%' is not a known regexp operator
gawk: cmd. line:1: warning: regexp escape sequence `\&' is not a known regexp operator
gawk: cmd. line:1: warning: regexp escape sequence `\,' is not a known regexp operator
gawk: cmd. line:1: warning: regexp escape sequence `\:' is not a known regexp operator
gawk: cmd. line:1: warning: regexp escape sequence `\;' is not a known regexp operator
gawk: cmd. line:1: warning: regexp escape sequence `\=' is not a known regexp operator
gawk: cmd. line:1: warning: regexp escape sequence `\@' is not a known regexp operator
gawk: cmd. line:1: warning: regexp escape sequence `\_' is not a known regexp operator
gawk: cmd. line:1: warning: regexp escape sequence `\~' is not a known regexp operator
"^(?=.*[\\]\\[!¡\'=ªº\\-\\_ç@#$%^&*(),;\\.?\":{}|<>\+\\/])"
] [ - _ . /
,它们必须加上双斜杠。如果不这样做,你的代码会出现类型错误。
escape()
”这样的函数,允许使用任意字符串作为正则表达式的一部分。 - ivan_pozdeev