2012-03-15 110 views
7

我想构建一个正则表达式,它匹配'",然后匹配其他字符,当分别匹配'"时结束,具体取决于在右边遇到的情况开始。所以这个问题看起来简单得足以在最后使用反向引用来解决;这里是下面一些正则表达式的代码(这是在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' ...但这显然是不够的,我需要整个字符串进行匹配。

我在想什么,是我需要一种方法来忽略第一组中不匹配的引号类型,方法是将其作为第三组字符集中的一个字符。但是,我知道没有办法做到这一点。有没有某种鬼鬼祟祟的非反向引用功能或某种东西?我可以用来引用第一组中不匹配的字符?或者以其他方式解决我的困境?

+0

嗨,欢迎来到StackOverflow。我冒昧地重新格式化您的文章一点。你可以点击编辑链接查看我是如何做到这一点的。非常重要的是要知道你是否需要发布代码... – 2012-03-15 11:15:14

回答

12

这可以使用负数lookahead assertions来完成。下面的解决方案,甚至考虑到了,你能逃脱在字符串中报价:

(["'])(?:\\.|(?!\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""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); 
+0

+1为一个深思熟虑和解释的解决方案! – FloppyDisk 2012-03-15 11:22:16

+0

杰出的工作Tim,感谢您编辑我的文章。感谢你的建议,通过一些工作,我修改了我的代码:“(['\”])([a-zA-Z])((?!\\ 1)[a-zA-Z0-9 ():; /''\“\\ = \\。\\,\\ - ])+(\\ 1)”这样你的解决方案实际上已经够简单和完美的了。如果在主要字符集之前有一个正则表达式,则添加正则表达式的等价关系,这将直接跳到最后一个循环。并将这两种类型的引号添加到主要字符集。这样,如果在任何时候发现了开始的引用char,则正则表达式将终止并返回。尼斯。 – 2012-03-15 11:36:40

2

蒂姆的解决方案工作得相当好,如果你可以使用环视(其中的Java不支持)。每种情况下单独

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

比赛,而是返回两种情况下:但是,如果你要使用的语言或工具,它不支持环视发现自己,你可以简单地匹配两种情况下(双引号字符串和单引号的字符串)分别作为整个匹配


无论其

这两种情况可以牺牲品至少一个不测。如果不仔细看,你可能会觉得应该有在此摘录比赛:

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

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

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

这个摘录只包含ONE比赛:

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

你能找到那个吗? :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' 

我会建议(如果你是为使用环视),您考虑做一些额外的检查(如空格或第一次报价之前类似的积极的回顾后),以确保你不” t匹配's trolleys collided with Mike'之类的东西 - 尽管如果没有大量测试,我不会在任何解决方案上投入太多资金。添加(?<=\s|^)要么表达年初将避免上述情况...即:

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

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

我不知道怎么环视效率相比于非环视,所以两个以上可能是等价的,或者一个可能比另一个更有效率(?)

+0

这里有一些好点的代码骑师,并且确实以这种方式解析英文文本不是明智的。然而,我实际上试图解析MySQL代码中的俄文文本(我在上面的代码中将а-яА-ЯёЁ更改为a-zA-Z,以便这里的人员能够掌握其含义),并且在解析字符串在代码中,它们当然总是保证被一种引号或另一种引用。 – 2012-03-15 15:41:19