我在这里看到一个SO问题,它使用Java Matcher
和Pattern
来尝试突出显示文本,类似于Regex101突出显示的方式。他的规范是在JTextArea中突出显示任何前面没有文字字符“#”的文字字符串。我打算建议创建你自己的Matcher
,然后OP删除了他的问题:(
那是背景,现在这是我的问题。我如何使用正则表达式来获取文字字符串,除非它在一行中的特定字符串/字符之后(但不是必须相邻)?
示例,如果我想从以下
中选择字符串“tester”tester,#thetes
测试测试员#测试测试员
测试
我希望我的正则表达式会选择
测试人员,#testter
测试测试人员 #test tester
测试
但不是最后一位“测试员”。
使用Regex101,我得到的最接近的是/(?=tester)(?<!#)tester/g
,但这会选择最后一个“测试者”字符串,因为我无法做“动态”?据我所知,(非零)长度回顾。
编辑:
我的问题不是Java特定的,否则我会放置Java标记。除非Regex101错误,否则我不能使用Limiting Repetition,因为“Lookbehinds需要为零宽度,因此不允许使用量词”。
我在Java中测试了WiktorStribiżew正则表达式,它运行正常。看到它是一个评论,而不是一个答案,我所能做的就是+1,Java String是(?<!#.{0,1000})\\btester\\b
。我根据以下Java字符串tester, #tester\ntest tester # test testern\tester
附带问题,还没有完全定义的方法来处理所有语言的正则表达式?或者Regex101只是一个糟糕的测试工具(我使用的是默认的PHP引擎)?
我将来会考虑使用RegexStorm或RegexHero。
答案 0 :(得分:1)
在Java中,如果预期子字符串之前的字符数不是无限的,您可以利用约束宽度的lookbehind 。这意味着你可以在lookbehind中使用限制量词。 (有一个允许在Java 8中使用*
的错误,但是利用它不是一个好主意,因为在其他版本中可能会修复错误。)请注意,限制量词内部的值越大,性能越高可能会下降。
所以,你可以使用
String rx = "(?<!#.{0,1000})\\btester\\b";
请参阅IDEONE demo
该模式匹配任何整个单词tester
(因为\b
是一个单词边界),前面没有#
,后跟0到1000任何字符,但是换行符(带{ {1}},它也会匹配换行符。
在线测试中的注意事项:因为regex101不支持具有约束宽度外观的正则表达式(如Java或ICU)。使用基于.NET的在线测试人员,例如RegexStorm或RegexHero。或者只使用最好的Java正则表达式在线测试人员:RegexPlanet或ocpsoft 。
<小时/> 现在, 谈论通用解决方案 :Match what you do not need, and match and capture what you need to keep.。
这是the pattern:
DOTALL
请注意,绿色突出显示的#.*\btester\b|\b(tester)\b
是驻留在捕获组#1中的那些,而组0中的那些是regex101中的蓝色。您可以检查这些子值属于哪个组,并在代码中采取适当的操作。
在Java中,要检查组是否匹配,只需使用
tester
答案 1 :(得分:0)
您可以使用以tester
开头的#
之前的可选组。然后检查是否存在第一组并相应更换。
String text = "tester, #tester\ntester foo\ntest tester # test tester\ntester";
Pattern p = Pattern.compile( "(#[^#\n]*)?(\\btester\\b)" );
Matcher m = p.matcher( text );
StringBuffer sb = new StringBuffer();
while(m.find()) {
if (m.group(1) == null)
m.appendReplacement(sb, "<em>" + m.group(2) + "</em>");
else
m.appendReplacement(sb, m.group());
}
m.appendTail(sb);
System.err.println(sb);
<强>输出:强>
<em>tester</em>, #tester
<em>tester</em> foo
test <em>tester</em> # test tester
<em>tester</em>
答案 2 :(得分:0)
虽然我最初认为这更像是在Java中突出显示匹配,但我发现here这段代码可以解决您的所有问题。略有改动以符合您的示例:
JTextArea textArea = new JTextArea(10, 30);
String text = "test tester # test tester";
textArea.setText(text);
Highlighter highlighter = textArea.getHighlighter();
HighlightPainter painter =
new DefaultHighlighter.DefaultHighlightPainter(Color.pink);
int p0 = text.indexOf("tester");
int p1 = p0 + "tester".length();
highlighter.addHighlight(p0, p1, painter );
JOptionPane.showMessageDialog(null, new JScrollPane(textArea));
如果您仅在p0==0
或text.charAt(p0-1) != '#'
时应用突出显示,则您不需要正则表达式。 (或者p0 < text.indexOf("#")
时,我不确定你想要什么。)