【问题标题】:How to select words having 3 and more characters between 2 words如何选择两个单词之间有 3 个或更多字符的单词
【发布时间】:2012-12-31 10:58:09
【问题描述】:

下面的文本是使用正则表达式从一个巨大的文本中过滤出来的,我必须在其中找到包含 dog 和 cat 而没有 porc 和 pig 的句子。

What, a Dog, a Rat, a Mouse, a Cat to scratch a man to
Where Iuliet liues, and euery Cat and Dog,
Which first (perchance) shee'l proue on Cats and Dogs,
glass, and from setting up memorials of departed cats and dogs.
Thinking,' etc., 1873, p. 82.), "A dog frames a general concept of cats or
dog, who never passed a cat who lay sick in a basket, and was a great

为了找到上面的内容,我使用了正则表达式:

^(?!.\*porc.\*)(?!.\*pig.\*)(?=.\*\bdog\b.\*)(?=.\*\bcat\b.\*).\*

现在,我必须在 dog 和 cat 之间找到包含 3 个或更多字符的单词。

我试过了:

^(?!.\*porc.\*)(?!.\*pig.\*)(?=.\*\bdog\b.\*)(?=.\*\bcat\b.\*)dog(?:\s?\w{3,})+cat

它不起作用。

有人知道如何解决吗?

【问题讨论】:

  • 在给定的示例文本中,您究竟想检索什么?我不是很清楚。如果您可以显示一些示例输出...
  • 根据我的经验,当涉及到复杂的逻辑(例如在其他单词之间搜索单词)时,正则表达式不是一个好工具。我建议使用不同的工具来提取所需的子字符串,然后将简单的搜索正则表达式应用于每个子字符串。
  • 您可以使用indexOf 来检查而不是在正则表达式中环顾四周。如果字符串有多个dogcat,您的预期输出是什么?

标签: regex regex-negation regex-lookarounds


【解决方案1】:

让我先说我对 Java 的熟悉程度不是最好的(我在声明任何语言隶属关系之前回答了这个问题)。话虽如此,我认为您的问题将需要两个正则表达式,因为(据我所知)Java 不支持捕获重复组。为了说明您需要什么,请考虑您正在寻找的整体模式。我在双星号中包含了您第一个示例中的匹配项(“什么,狗,老鼠,老鼠,猫抓人”):

(?P<animal>    // Names the following group "animal" for later reference
    \b(dog|cat)    // **Dog**
)    // Ends "animal" group
[s]?\b\W+    // **, **
(?!\bporc\b\W+|\bpig\b\W+|(?P=animal)\W+)    // Not followed by porc, pig, or characters that match group "animal" (either 'cat' or 'dog')
.*?    // Characters up to first word of three characters or more **a **
(
    (
        (
            (
                (\b\w{3,}\b)    // The (repeated) group you are after (**Rat** / **Mouse**)
            \W+)+    // (**, ** / **, **)
        )
            (?:\b\w{0,2}\b\W+)*    // A group that will not be available after the search (**a ** / **a **)
        )+
    )
(?!    // Not followed by 
    (?P=animal)    // the characters that matched group "animal" above (either dog or cat)
)\b
(cat|dog)[s]{0,1}\b    // Followed by dog or cat, whichever was not the "animal" group above **Cat**

由于 Java 只会捕获最后一个重复组(与 .NET 和其他允许捕获重复组的语言不同),您很可能需要分两步进行查询。首先,您需要找到 cat(s) or dog(s) 和 dog(s) or cat(s) 之间的所有字符串(只要第一组不同于第二组)。您可以使用如下的正则表达式找到这些字符串:

(?P<animal>\b(dog|cat))[s]{0,1}\b\W+(?!\bporc\b\W+|\bpig\b\W+|(?P=animal)\W+)(.*?)(?!(?P=animal))\b(cat|dog)[s]{0,1}\b

您会想要找到第 3 组,即 (.*?)。

在每个相关字符串/句子中识别出第 3 组后,您可能希望使用如下内容(基于 this post):

Pattern regex = Pattern.compile("\b\w{3,}\b");
Matcher regexMatcher = regex.matcher(subjectString);
while (regexMatcher.find()) {
    // matched text: regexMatcher.group()
    // match start: regexMatcher.start()
    // match end: regexMatcher.end()
} 

不幸的是,您不能只使用一个(合理的)正则表达式来捕获 Java 中需要的所有单词,因为您永远不知道单词 dog 和 cat 之间会出现多少个三个字母的单词。我希望这会有所帮助。

【讨论】:

  • 我刚刚更新了答案。鉴于您使用的是 Java,我希望它更清楚。
猜你喜欢
  • 2015-09-08
  • 2015-04-08
  • 1970-01-01
  • 2014-01-26
  • 2011-11-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-13
相关资源
最近更新 更多