我有一个正则表达式,它选择包含所有(不是!任意)特定字母的所有单词,只需在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兼容版本是什么?
答案 0 :(得分:2)
将您的Pattern
更改为:
String patternString = ".*(?=.*B)(?=.*L)(?=.*T).*";
输出
Match: LABAT
Match: BALAT
Match: LATAB
答案 1 :(得分:1)
在现实生活中,我们很少需要验证行,我发现事实上,您只是将输入用作测试数据的数组。最常见的情况是逐行读取输入并对其执行检查。我在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 class和possessive 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
。