7

我想构造一个正则表达式,它匹配'or"然后匹配其他字符,在分别匹配 a'或 an时结束",具体取决于在开始时遇到的内容。所以这个问题看起来很简单,可以在最后使用反向引用来解决;下面是一些正则表达式代码(它在 Java 中,所以请注意额外的转义字符,例如\之前的"):

private static String seekerTwo = "(['\"])([a-zA-Z])([a-zA-Z0-9():;/`\\=\\.\\,\\- ]+)(\\1)";

此代码将成功处理以下内容:

"hello my name is bob"
'i live in bethnal green'

当我有这样的字符串时,麻烦就来了:

"hello this seat 'may be taken' already"

使用上面的正则表达式将在遇到初始部分时失败,'然后它将继续并成功匹配'may be taken'......但这显然是不够的,我需要匹配整个字符串。

我在想的是,我需要一种方法来忽略第一组中不匹配的引号类型,方法是将其作为字符包含在第三组的字符集中。但是,我知道没有办法做到这一点。是否有某种鬼鬼祟祟的 NOT 反向引用函数之类的?我可以用它来引用第一组中不匹配的字符??或者以其他方式解决我的困境?

4

2 回答 2

12

这可以使用否定的前瞻断言来完成。以下解决方案甚至考虑到您可以在字符串中转义引号:

(["'])(?:\\.|(?!\1).)*\1

解释:

(["'])    # Match and remember a quote.
(?:       # Either match...
 \\.      # an escaped character
|         # or
 (?!\1)   # (unless that character is identical to the quote character in \1)
 .        # any character
)*        # any number of times.
\1        # Match the corresponding quote.

这正确匹配"hello this seat 'may be taken' already"or "hello this seat \"may be taken\" already"

在 Java 中,带有所有反斜杠:

Pattern regex = Pattern.compile(
    "([\"'])   # Match and remember a quote.\n" +
    "(?:       # Either match...\n" +
    " \\\\.    # an escaped character\n" +
    "|         # or\n" +
    " (?!\\1)  # (unless that character is identical to the matched quote char)\n" +
    " .        # any character\n" +
    ")*        # any number of times.\n" +
    "\\1       # Match the corresponding quote", 
    Pattern.COMMENTS);
于 2012-03-15T11:05:44.543 回答
2

如果您可以使用环视(Java 确实支持),Tim 的解决方案效果很好。但是,如果您发现自己使用的语言或工具不支持环视,您可以简单地分别匹配两种情况(双引号字符串和单引号字符串):

"(\\"|[^"])*"|'(\\'|[^'])*'

分别匹配每个案例,但返回任一案例作为整个匹配


然而

这两种情况都可能成为至少一种可能性的牺牲品。如果不仔细看,你可能会认为这段摘录中应该有两个匹配项:

他转身骑上他的自行车。“等我做完这一切后再见。”他说,在开始他的旅程之前回头看了一会儿。当他进入街道时,一辆城市的手推车与迈克的自行车相撞。“天啊!” 一个旁观者惊呼道。

...但是有场比赛,而不是两场:

"I'll see you later, when I'm done with all this"
's trolleys collided with Mike'
"Oh my!"

此摘录仅包含一个匹配项:

不过,战斗还没有结束。“嘿!” 鲍勃喊道。“你想要什么?” 我反驳道。“你让我恶心!” “我为什么要关心?” “因为我爱你!” “你做?” 鲍勃停顿了片刻,然后低声说:“不,我不能爱你!”

你能找到那个吗?:D

't over yet, though. "Hey!" yelled Bob. "What do you want?" I retorted. "I hate your guts!" "Why would I care?" "Because I love you!" "You do?" Bob paused for a moment before whispering "No, I couldn'

我建议(如果您准备使用环视),您考虑做一些额外的检查(例如在第一个引号之前对空格或类似内容进行积极的后视)以确保您不匹配类似的东西's trolleys collided with Mike'- 尽管我不会'在没有先进行大量测试的情况下,不会在任何解决方案上投入大量资金。添加(?<=\s|^)到任一表达式的开头将避免上述情况......即:

(?<=\s|^)(["'])(?:\\.|(?!\1).)*\1                    #based on Tim's

或者

(?<=\s|^)("(\\"|[^"])*"|'(\\'|[^'])*')               #based on my alternative

我不确定环视与非环视相比效率如何,因此上述两个可能是等效的,或者一个可能比另一个更有效(?)

于 2012-03-15T13:32:15.793 回答