这个正则表达式是什么意思?

12

最近我接受了一次采访,被要求解读这个正则表达式

^\^[^^]

你能帮我解决一下这个问题吗?也请提供一些关于正则表达式面试的学习链接。


2
如果您发布实际的正则表达式而不是带有痛苦和有时具有欺骗性的反斜杠的Java字符串,那将会更清晰明了。 - tchrist
1
@tchrist - 为什么?他说这个字符序列是在面试中给他的,我猜是Java相关的面试,看标签就知道了。(顺便说一句 - 正则表达式标签是由其他人添加的,最初只有Java标签) - Andreas Dolk
1
@Andreas_D,我不想承认因为反斜杠问题而搞砸Java正则表达式的次数有多少。现在我从props文件或作为命令行参数读取它们(尝试)避免这个问题。即便如此,Java字面用作正则表达式和实际正则表达式之间存在很大差异。这就像与shell打交道,但更糟糕。 - tchrist
2
正则表达式不需要两个反斜杠来转义正则元字符,只需要一个反斜杠。第二个反斜杠仅在将正则表达式编码为Java字符串常量时才需要。该问题要求解密正则表达式,而不是作为Java字符串编码的正则表达式,并且没有周围的引号。因此,我已将正则表达式恢复到最初发布的状态。 - JeremyP
4
另一位自以为非常聪明的面试官。天啊。 - Sean Patrick Floyd
显示剩余2条评论
4个回答

30

它匹配以^开始,后跟任何一个字符(除了^)的字符串。

因此,它会匹配:

^foo
^b

但不是

foo
^^b

解释:

Caret^)是一个正则表达式元字符,具有两种不同的含义:

字符类之外(你的正则表达式中的第一次使用),它作为起始锚点工作。

^作为字符类第一个字符使用(你的正则表达式中的第三次使用)时,它在字符类内部充当否定字符

通过在正则表达式前面添加\对其进行转义(使其变为普通字符)。你的正则表达式中的第二次使用的^被转义,并且它匹配字符串中的字面量^

在字符类中,不是字符类第一个字符的^会被视为字面量。因此,你的正则表达式中的第四次使用是一个字面量的^

以下是更多示例,以使其更清晰:

  • ^a         :匹配以 a 开头的字符串
  • ^ab       :匹配以 a 开头,后跟b 的字符串
  • [a]       :匹配包含 a 的字符串
  • [^a]     :匹配不包含 a 的字符串
  • ^a[^a] :匹配以 a 开头,后跟除 a 之外的任何字符的字符串

1
如果您假设此正则表达式位于引号内,则这是正确的。否则,它将成为一个字面上的“\”。 - Matt Bridges
2
@Matt:我假设是因为 Java 标签。 - Matt K
3
@Matt,我认为这是一个安全的假设,因为如果字面意义上的反斜杠是有意义的,那么正则表达式永远不会匹配任何字符串。 - Bart Kiers
1
由于正则表达式只匹配2个字符,我认为匹配示例最好是匹配“^bar”中的“^b”和“^foo”中的“^f”。 - jwernerny
我真的应该投反对票,因为“在正则表达式之前加上\进行转义”是错误的。在正则表达式中,只使用一个反斜杠来转义一个字符。我没有投反对票,因为你假设正则表达式在Java常量字符串中,这种情况下正则表达式转义必须是字符串转义。 - JeremyP
显示剩余3条评论

3
我正在测试这个正则表达式(在此处),但它似乎无效。
第一个^表示行的开头。
第一个\转义了后面的\
因此第二个"^"没有被转义。 最后方括号内的第一个插入符[^作为否定,第二个插入符^]没有被转义,结果无效。

我认为正确的正则表达式应该是^\^[^\^]
大家能确认一下吗?非常感谢。


2
我认为有一个隐含的假设,即这是在引号内,因此需要两个反斜杠来转义第二个脱字符。 - Matt Bridges
谢谢,只是确保一下。 - Philar

2

匹配行首或字符串开头, 紧跟着一个字面上的反斜杠, 再紧跟着行首或字符串开头, 最后紧跟着任何非空格、回车或换行符的字符。


这是一个流行的学习正则表达式的网站:http://www.regular-expressions.info/tutorial.html - Mike Cheel
这是错误的:除非您处于(?m)模式,否则不能通过^拥有两个字符串/行标记。最明显的答案是它匹配以插入符号后跟任何非插入符号字符开头的行,但由于愚蠢的Java松散反斜杠,这很难说清楚。 - tchrist
我并没有说它是正确的或者与任何东西匹配。我只是说了它所说的内容。 - Mike Cheel
@tchrist 我明白。就像我说的,我只是在说正则表达式的内容。将其放入解释正则表达式的引擎中(我使用了Expresso),你就可以看到我所说的是正确的。 - Mike Cheel
@tchrist 我认为问题在于不同的引擎都有自己的方式(类似于浏览器),因此虽然大多数事情应该在所有引擎中都能正常工作,但某些东西的解释方式可能会有所不同。一个很好的例子是在http://www.regular-expressions.info/lookaround.html上。 - Mike Cheel
显示剩余3条评论

2

第一个^是行的开头。

第二个^是字面上的字符 (\是为了转义^的其他常见含义)。

第三个是表示

不包括字符^的一类字符

以下是使用Ruby的一些示例:

ruby-1.9.2-p0 > "hello" =~ /^h/    # it found a match at position 0
 => 0 

ruby-1.9.2-p0 > "hello" =~ /^e/    # nil means can't find it
 => nil 

ruby-1.9.2-p0 > "he^llo" =~ /\^/   # found at position 2
 => 2 

ruby-1.9.2-p0 > "he^llo"[/[^^]*/]  # anything repeatedly but not including the ^ character
 => "he" 

@動靜能量 - 在你的例子中,你忽略了“第二个” - 它只会匹配以^开头的字符串。而这个^是匹配的一部分("^hel^lo" -> "^hel")。 - Andreas Dolk
这个例子中的第三种情况是展示匹配字面量^,这是您的意思吗? - nonopolarity
@动静能量 - 我错了,第一次阅读时我以为这些例子会说明原始模式的行为。(顺便说一句 - 不是我对答案进行了投票) - Andreas Dolk

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接