【问题标题】:Far Negative Lookbehind远负回顾
【发布时间】:2013-01-31 12:36:45
【问题描述】:

如何更改我的pattern 以进一步查看字符串?

当“段落”一词在模式(alpha)后面时,匹配为假,否则为真。

例如,这将有 5 个匹配项:

代表 (a)、(b)、(c)、(d) 或 (e) (f)款;

他们将是:(a)(b)(c)(d)(e)

这将有 0 个匹配项:

代表 (a)、(b)、(c) 段中提及的任何人行事, (d) 或 (e);

【问题讨论】:

  • 我不明白你问题的第二段。 :)
  • @Threat 是的,更好的是,您可以以相反的方式思考您的问题。尝试匹配那些“假”的情况。它可以使它更容易。详情请查看我的答案。

标签: java regex


【解决方案1】:

这对于任何长度的简单回顾都是不可能的。 Java regex 风格只允许有限长度的lookbehind(即你可以做(?<=x{2,10}) 但不能做(?<=x*))。

如果您可以将问题简化为“paragraph 这个词不应该出现在(a) 前面的 100 个字母中”,那就行了:

(?<!paragraph.{0,100})\([a-z]\)

如果你真的想要无限距离并且如果你的正则表达式是灵活的并且可以从输入的开头开始并且只匹配一个(ref),你可以用负前瞻来近似想要的行为(不必是有限的):

^(?!.*?paragraph.*?\([a-z]\)).*?\([a-z]\)

将匹配 test test (a) 但不匹配 paragraph test (a)。

这是一个技巧,虽然维护起来可能会变得相当复杂,也有缺点(比如只匹配一次),最终可能会有更好的方法来解决您的问题。例如,您可以匹配所有([a-z]),然后检查字符串是否包含paragraph,消除其位置之后的所有匹配项。

PS:请考虑使用Pattern.compile("abc", Pattern.CASE_INSENSISIVE) 或Pattern.compile("(?i)abc")(如果整个正则表达式不区分大小写)或Pattern.compile("(?i:abc)dEf")(如果只有abc 不区分大小写)来代替Pattern.compile("[aA][bB][cC]")。

【讨论】:

  • 您可以在www.gskinner.com/RegExr 中尝试吗?出于某种原因,test test (a) 和 paragraph test (a) 不适合我
  • RegExr 使用 ActionScript 3 的正则表达式风格:gskinner.com/blog/archives/2008/03/regexr_free_onl.html
  • 是的。您能否发布一个链接来展示您的模式。
  • 是的,问题之前说过。但是(a) paragraph (b) 不会(甚至在(a) 上也不会),这是限制之一……因此我不会盲目推荐这种方法。
【解决方案2】:

你可以这样做:

(我忽略了大小写密集部分,您可以自己添加)

".*Paragraph.*\\(a\\)" 

这是检查您的FALSE 案例是否匹配。也就是说,(a) 前面有 paragraph。

然后检查该行是否与上面的正则表达式匹配,如果为真,则跳过,如果为假,则接受。

用 grep 测试:(-v 用于显示不匹配的行)

kent$  cat test.txt
(a)
Paragraph (a)
(b) (c)
foo bar Paragraph (a) (b)
foo bar Paragraph (some) (a) (b)
foo bar (a) (b) Paragraph (c)

kent$  grep -v '.*Paragraph.*\(a\)' test.txt
(a)
(b) (c)
foo bar (a) (b) Paragraph (c)

有一个小问题是,如果该行没有Paragraph 并且没有(a),也会被匹配。我认为这也很容易通过以下方式在您的 java 程序中修复:

if (!m.find() && line.indexOf("(a)")>0) ...your match   

【讨论】:

  • 肯特你能尝试在www.gskinner.com/RegExr上运行这个模式并分享一个链接
  • @ThreaT 我避免这样做。 :)
【解决方案3】:

你可以这样做:

// If "paragraph" (case insensitive) does not appear before any (<alpha>)
// It means that "paragraph" (case insensitive) will appear after one (<alpha>)
// OR it does not appear at all in the string.
if (!str.matches("(?s)(?:(?!\\([a-z]+\\)).)*(?i:paragraph).*")) {
    // Use the Matcher loop to extract the text that matches pattern "\\([a-z]+\\)"
    Pattern p = Pattern.compile("\\([a-z]+\\)");
    Matcher m = p.matcher(str);

    while (m.find()) {
        System.out.println(m.group());
    }
}

在提取所有(&lt;alpha&gt;) 之前,只需检查paragraph 没有出现在所有(&lt;alpha&gt;) 之前。这适用于任何长度的字符串。

【讨论】:

    猜你喜欢
    • 2013-08-03
    • 1970-01-01
    • 2018-01-02
    • 2016-05-19
    • 1970-01-01
    • 1970-01-01
    • 2016-09-07
    • 2023-03-22
    • 1970-01-01
    相关资源
    最近更新 更多