0

在最近的一次使用中String.split(),我遇到了这样一种情况,即文本是如此动态,选择匹配项比过滤掉不匹配项更容易。

我发现自己想知道是否可以修改“反向正则表达式”,String.split()以便您可以给它任何模式,它会匹配与该模式不匹配的每一组字符。

*注意:这里的“问题”可以用String.matches(), Tokens,Matcher.group()等轻松解决。这个问题主要是假设性的(仍然欢迎代码示例,因为问题的性质非常需要它),而不是关于如何获得结果,而是关于是否有可能以这种方式实现它们


我尝试了什么:

String pattern1 = "(test)"; //A verif. that what "should-not-match" is working correctly.
        String pattern2 = "[^(test)]"; //FAIL - unmatches the letters separately.
        String pattern3 = "(^(test))"; //FAIL - does not match anything, it seems.
        String text = ""
                        + "This is a test. "
                        + "This test should (?not?) match the word \"test\", whenever it appears.\n"
                        + "This is about to test if a \"String.split()\" can be used in a different way.\n"
                        + "By the way, \"testing\" does not equal \"test\","
                        + "but it will split in the middle because it contains \"test\".";
        for (String s : text.split(pattern3)) {
            System.out.println(s);
        }

以及其他类似的模式,但都没有成功。


更新:

我现在也尝试了一些使用特殊构造函数的模式,但也没有让它工作。

至于我想要什么,按照“测试”示例,是获取一个包含内容为“文本”的字符串的数组(我想用作基本模式,或者换句话说,我想要查找的内容)。

但是这样做使用String.split(), with 使得使用基本模式直接导致“任何不是(测试)”,因此需要反转以导致“只是(测试)的出现”。

Bible-sized-long-story-short,想要的是String.split()导致这种行为的正则表达式(+结果):注意:遵循上面的示例代码,包括所需的变量(文本)。

String[] trash = text.split("test"); //<-base pattern, needs reversing.
        System.out.println("\n\nWhat should match the split-pattern (due reversal), become separators, and be filtered out:");
        for (String s : trash) {
            System.out.println("[" + s + "]");
            text = text.replace(s, "%!%"); //<-simulated wanted behavior.
        }
        System.out.println("\n\nWhat should be the resulting String[]:");
        for (String s : text.split("%!%")) {
            System.out.println(s);
        }
        System.out.println("Note: There is a blank @ index [0], since if the text does not start with \"test\", there is a sep. between. This is NOT WRONG.");

欢迎使用代码示例。毕竟,创建此类代码的可能性(或不可能性)是这个问题的本质。

4

2 回答 2

3

您可能正在谈论 (?! 构造。

它记录在 Pattern 类的 javadoc 中。他们称之为消极的前瞻性断言。

解决问题最直接的方法是重复查找。

    Pattern p = Pattern.compile(regexForThingIWant);
    Matcher m = p.matcher(str);
    int cursor = 0;
    while (m.find(cursor)) {
      String x = m.group();
      // do something with x
      cursor = m.end();
    }

我能够为似乎做你想做的事情的分裂拼凑一个正则表达式,但很糟糕:

(^|(?<=test))((?!test).)*
于 2012-07-19T18:02:50.090 回答
0

我很难看到split您想看到的输出,因为您唯一的提示是测试字符串的一部分,然后只是间接的(就像您希望单词testing分成两部分一样)。

好吧,让我们尝试一个积极的回顾:

^|(?<=test)

这返回

This is a test
. This test
 should (?not?) match the word "test
", whenever it appears.
This is about to test
 if a "String.split()" can be used in a different way.
By the way, "test
ing" does not equal "test
",but it will split in the middle because it contains "test
".

那是你想要的吗?

请注意,当以这样一种方式拆分文本时,输入的“匹配”和“不匹配”位(在松散意义上)都不会被拆分过程消耗,您需要设计正则表达式,使其仅匹配(一些)空字符串,在“匹配”这个词的技术意义上。

因此,前瞻和后瞻几乎是您使用正则表达式解决此类任务的唯一工具。

但是,如果您希望消耗所有非测试部件,那也是可以实现的。

(?<=^|(test))(tes[^t]|te[^s]|t[^e]|[^t])*

它是相同的lookbehind,然后消费任何看起来不像这个词的东西test

但是,这种方法并不完全通用。 这个问题解释了限制。

于 2012-07-19T18:35:50.727 回答