Java重复模式匹配(3)

时间:2011-10-16 19:20:51

标签: java regex matching repeat

我正在尝试解决一个简单的Java正则表达式匹配问题,但仍会收到相互矛盾的结果(跟进thisthat问题)。

更具体地说,我正在尝试匹配重复文本输入,其中包含由“|”分隔的组(垂直条)可能直接以下划线('_')开头,特别是如果组不为空(即,如果输入中没有出现两个连续的分隔符)。

此类输入的示例是:

Text group 1_|Text group 2_|||Text group 5_|||Text group 8

此外,我需要一种方法验证匹配是否已发生,以避免将与该输入相关的处理应用于我的应用程序也处理的其他完全不同的输入,使用不同的正则表达式。

要确认正则表达式有效,我使用的是RegexPal

经过多次测试后,最接近我想要的是以下两个正则表达式,在我上面引用的问题中提出:

1. (?:\||^)([^\\|]*) 
2. \G([^\|]+?)_?\||\G()\||\G([^\|]*)$

使用其中任何一个,如果我运行 matcher.find()循环,我得到:

  • 所有文本组,最后都包含下划线,来自Regex 1
  • 除最后一个之外的所有文本组,最后没有下划线但最后有两个空组,来自正则表达式2.

所以,显然Regex 2不正确(RegexPal也没有将其显示为匹配)。

我可以使用正则表达式1 并进行一些后期处理以删除尾随下划线,但理想情况下我希望正则表达式为我做。

但是,上述两个正则表达式中没有一个为 matcher.matches()返回true,而 matcher.find()始终为true,即使对于完全无关的输入也是如此(合理的,因为通常会有至少1个匹配组,即使在其他文本中也是如此)。

因此我有两个问题

  1. 是否有正确的(完全正常)正则表达式排除尾随下划线
  2. 有没有办法检查只有正确的正则表达式匹配
  3. 用于测试Regex 1的代码类似于

    String input = "Text group 1_|Text group 2_|||Text group 5_|||Text group 8";
    
    Matcher matcher = Pattern.compile("(?:\\||^)([^\\\\|]*)").matcher(input);
    
    if (matcher.matches())
    {
        System.out.println("Input MATCHED: " + input);
    
        while (matcher.find())
        {
            System.out.println("\t\t" + matcher.group(1));
        }
    
    }
    else
    {
        System.out.println("\tInput NOT MATCHED: " + input);
    }
    

    使用上面的代码总是会产生“NOT MATCHED”。删除if / else并仅使用 matcher.find()检索所有文本组

2 个答案:

答案 0 :(得分:1)

Matcher#matches方法尝试将整个输入序列与模式匹配,这就是获得结果Input NOT MATCHED的原因。请参阅此处的文档http://download.oracle.com/javase/1.4.2/docs/api/java/util/regex/Matcher.html#matches

如果要排除尾随下划线,可以使用此正则表达式(略微修改已有的内容)

(?:\\||^)([^\\\\|_]*)

如果您确定_出现在|之前,这将有效。

答案 1 :(得分:1)

RegexPal是一个JavaScript正则表达式工具。 Java和JavaScript正则表达式语言不同。考虑使用Java Regex工具;也许this one

这可能接近你想要的:(?:([^_\|]+)_{0,1}+\|*)+

修改: 已添加代码。 在java 6中,它打印每个组(find()循环)。

public static void main(String[] args)
{
    String input = "Text group 1_|Text group 2_|||Text group 5_|||Text group 8";
    Matcher matcher;
    Pattern pattern = Pattern.compile("(?:([^_\\|]+)_{0,1}+\\|*)+");
    Pattern groupPattern = Pattern.compile("(?:([^_\\|]+)_{0,1}+\\|*)");

    matcher = pattern.matcher(input);
    if (matcher.matches())
    {
        Matcher groupMatcher;

        System.out.println("matcher.matches() is true");
        int groupCount = matcher.groupCount();
        for (int index = 1; index <= groupCount; ++index)
        {
            System.out.print("group (pattern)[");
            System.out.print(index);
            System.out.print("]: ");
            System.out.println(matcher.group(index));
        }

        groupMatcher = groupPattern.matcher(input);
        while (groupMatcher.find())
        {
            System.out.print("group (groupPattern):");
            System.out.println(groupMatcher.group());
                            System.out.println(groupMatcher.group(1));
        }
    }
    else
    {
        System.out.println("No match");
    }
}