包含Java中所有特定字母的正则表达式

时间:2015-11-20 14:01:17

标签: java regex

我有一个正则表达式,它选择包含所有(不是!任意)特定字母的所有单词,只需在Notepad ++上正常工作。

正则表达式模式;

^(?=.*B)(?=.*T)(?=.*L).+$

输入文本文件;

AL
BAL
BAK
LABAT
TAL
LAT
BALAT
LA
AB
LATAB
TAB

在notepad ++中输出正则表达式;

LABAT
BALAT
LATAB

由于它对Notepad ++有用,我在java上尝试了相同的正则表达式,但它只是失败了。

这是我的测试代码;

import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.lev.kelimelik.resource.*;

public class Test {

    public static void main(String[] args) {
        String patternString = "^(?=.*B)(?=.*T)(?=.*L).+$";

        String dictionary = 
                "AL" + "\n"
                +"BAL" + "\n"
                +"BAK" + "\n"
                +"LABAT" + "\n"
                +"TAL" + "\n"
                +"LAT" + "\n"
                +"BALAT" + "\n"
                +"LA" + "\n"
                +"AB" + "\n"
                +"LATAB" + "\n"
                +"TAB" + "\n";

        Pattern p = Pattern.compile(patternString, Pattern.DOTALL);
        Matcher m = p.matcher(dictionary);
        while(m.find())
        {
            System.out.println("Match: " + m.group());
        }
    }

}

输出错误,如下所示;

Match: AL
BAL
BAK
LABAT
TAL
LAT
BALAT
LA
AB
LATAB
TAB

我的问题很简单,这个正则表达式的java兼容版本是什么?

3 个答案:

答案 0 :(得分:2)

将您的Pattern更改为:

String patternString = ".*(?=.*B)(?=.*L)(?=.*T).*";

输出

Match: LABAT
Match: BALAT
Match: LATAB

答案 1 :(得分:1)

特定于Java的答案

在现实生活中,我们很少需要验证,我发现事实上,您只是将输入用作测试数据的数组。最常见的情况是逐行读取输入并对其执行检查。我在Notepad ++中同意这是一个不同的解决方案,但在Java中,应该单独检查一行。

那就是说,你不应该在不同的平台上复制相同的方法。 Notepad ++中的优点不一定非常好。

我建议这种几乎没有正则表达式的方法(String#split()仍然使用它):

String dictionary_str = 
        "AL" + "\n"
        +"BAL" + "\n"
        +"BAK" + "\n"
        +"LABAT" + "\n"
        +"TAL" + "\n"
        +"LAT" + "\n"
        +"BALAT" + "\n"
        +"LA" + "\n"
        +"AB" + "\n"
        +"LATAB" + "\n"
        +"TAB" + "\n";
String[] dictionary = dictionary_str.split("\n"); // Split into lines
for (int i=0; i<dictionary.length; i++)   // Iterate through lines
{
    if(dictionary[i].indexOf("B") > -1 && // There must be B
       dictionary[i].indexOf("T") > -1 && // There must be T
       dictionary[i].indexOf("L") > -1)   // There must be L
    {
        System.out.println("Match: " + dictionary[i]); // No need matching, print the whole line
    }
}

请参阅IDEONE demo

基于正则表达式的原始答案

你不应该依赖.*。此构造始终导致回溯问题。在这种情况下,您可以使用negated character classpossessive quantifiers

轻松优化它
^(?=[^B]*+B)(?=[^T]*+T)(?=[^L]*+L)

正则表达式分解:

  • ^ - 字符串开头
  • (?=[^B]*+B) - 在字符串的开头,检查至少一个B状态,其前面可能有B以外的0个或多个字符
  • (?=[^T]*+T) - 仍然在字符串的开头,检查至少一个T存在,其前面可能有0个或更多字符而不是{{1 }}
  • T - 仍然在字符串的开头,检查至少一个(?=[^L]*+L)存在,其前面可能有0个或更多字符,而不是{{1 }}

请参阅Java demo

L

输出:

L

答案 2 :(得分:1)

我没有调试你的情况,但我认为你的问题是由匹配整个字符串而不是单个单词引起的。

您正在匹配"AL\nBAL\nBAK\nLABAT\n"以及更多内容。当然,该字符串具有所有必需的字符。您可以看到输出只包含一个Match:前缀。

请查看this回答。您需要使用Pattern.MULTILINE