当用双引号封装时,转义序列与预定义的字符类(也称为特殊的正则表达式字符)

时间:2013-06-06 22:39:07

标签: java python regex perl

与Java和Python一样,Perl具有\s,除了其他特殊字符外,还有与空白匹配的特殊正则表达式字符。

在Perl中,以下内容无效:

my $sentence = "The End";
my $subStr = "\s"; #Does NOT work, needs to be "\\s" or '\s'

if ($sentence =~ /$subStr/)
{
    say "True";
}

在Java中,这是有效的:

String s = "The End";

if (s.matches(".*\\s.*")) //same deal as with Perl ("\\s")
{
    System.out.println("True");
}

在Python中,可以使用"\s"'\s'

Java和Perl似乎都将""封装的特殊正则表达式字符视为相同。我查了Predefined Character Classes(Java),它简单地说:“如果你在字符串文字中使用了一个转义构造,你必须在反斜杠之前加上另一个反斜杠来编译字符串。”

为什么Java和Perl对转义序列的处理方式与特殊的正则表达式字符不同(当它们都由""封装时),但是,python不是?

为什么设计师选择转义序列(如\n\t)要求一个反斜杠,但对于预定义的字符类,如\s,需要两个(在""中)?

这是别的结果吗?或者它是否以某种方式简化某种交互或者你有什么?

我将假设它不是任意的。 Python只需要\两种方式,但Perl和Java在处理\\时授权""。除了有点混乱,它只是凌乱。所以,我认为这个决定有充分的理由。谁知道为什么?

1 个答案:

答案 0 :(得分:8)

Java,Perl和Python都使用C风格的反斜杠进行转义。正则表达式还使用C风格的反斜杠进行转义。这导致了所有三种语言的问题 - 事实上,对于许多其他语言来说也是如此。

例如,所有三种语言都会将'\\'转换为单个反斜杠,'\n'转换为换行符等,然后才能进入正则表达式编译器。

唯一的区别是,在Python中,像'\s'这样的未知转义序列会自行解析,而在Java和Perl中,它们只能解析为's'。因此,在Python中,当您需要'\\\n'时,您不需要'\\s',而在Java和Perl中,您需要转义两者的反斜杠。

还有一些语言可以作为第三种选择,将未知的转义序列视为错误。


所以,如果你有记忆的已知转义列表,你有时可以逃脱Python中没有转义反斜杠。但你真的不应该。

为什么不呢?因为,即使你完全确定你已经记住了转义序列,你是否真的想要对那些想要阅读(或维护)你的代码的人提出这个要求?当我看到"abc\\sdef"r"abc\sdef"时,我立即确切地知道它意味着什么。当我看到未转义的"abc\sdef"时,我认为我知道,但我可能错了,我必须去查找或者在翻译中尝试找出来。


正确的做法是逃避反斜杠,或者为您的语言使用适当的原始字符串或正则表达式文字语法。


如果你想知道为什么Python为来自Perl和Java的未知逃逸做出了不同的设计选择...据我所知,官方Design FAQ没有涉及到这一点,并且Guido没有直接解决。但我可以猜到。一般来说,Perl与C(以及Java与C ++)的最大兼容性作为许多领域的高优先级,其中Python更优先考虑对编程教师更直观的意义。这可能是其中一个方面。 (我怀疑如果今天从头开始重新设计Python,或者甚至在添加原始字符串时重新设计,它会出错。)