负向前看匹配字符串,除非它出现在特定的单词中



我试图找到一种方法来确定一行是否包含一个特定的字符串,而在同一时间不匹配,如果它发生在某些单词。我有这部分工作,但它失败,如果排除的单词之一开始与关键字。

例如,这个正则表达式:^((?!custom|onetomany|manytomany|atom|tomcat|tomorrow|automatic).)*(tom)

将成功排除列出的所有单词,除了tomcat &明天。我假设这是因为我匹配的关键字,所以展望失败,但我不知道如何解决它。

更新:遗憾的是,我还没能弄清楚这一点,除非你在非捕获组的.的两侧都放上负向前看:

^(?:(?!custom|onetomany|manytomany|atom|tomcat|tomorrow|automatic).(?!custom|onetomany|manytomany|atom|tomcat|tomorrow|automatic))*?(tom).*


如果你把.移到你的负向前看之前,它会起作用:.(?!...)

我还将*重复设置为惰性,因此它不需要回溯那么多(并不总是正确的,但在本例中是这样)。此外,如果您想匹配整行并且只捕获tom的实例,则使包含.(?!...)的组不捕获,并使用贪心.*结束表达式:

^(?:.(?!custom|onetomany|manytomany|atom|tomcat|tomorrow|automatic))*?(tom).*

这种情况听起来很像匹配(或替换)模式,除了s1、s2、s3等情况。

与其他可能的解决方案相比,正则表达式再简单不过了:

custom|onetomany|manytomany|atom|tomcat|tomorrow|automatic|(tom)

如果您不仅想显示tom,还想显示它所在的整个单词,例如tomahawk,请将其更改为:

custom|onetomany|manytomany|atom|tomcat|tomorrow|automatic|(w*tomw*)

选项的左侧匹配您不想要的单词。我们将忽略这些匹配。右边匹配并捕获tom到组1,我们知道它们是右tom,因为它们没有被左边的表达式匹配。

这个程序展示了如何使用正则表达式(参见在线演示底部的结果)。它找到tomtomahawk

import java.util.*;
import java.io.*;
import java.util.regex.*;
import java.util.List;
class Program {
public static void main (String[] args) throws java.lang.Exception  {
String subject = "custom onetomany manytomany atom tomcat tomorrow automatic tom tomahawk";
Pattern regex = Pattern.compile("custom|onetomany|manytomany|atom|tomcat|tomorrow|automatic|(\w*tom\w*)");
Matcher regexMatcher = regex.matcher(subject);
List<String> group1Caps = new ArrayList<String>();
// put Group 1 captures in a list
while (regexMatcher.find()) {
if(regexMatcher.group(1) != null) {
group1Caps.add(regexMatcher.group(1));
}
} // end of building the list
System.out.println("n" + "*** Matches ***");
if(group1Caps.size()>0) {
for (String match : group1Caps) System.out.println(match);
}
} // end main
} // end Program
参考

如何匹配(或替换)模式,除了s1, s2, s3…

我想这就是你想要的:

b(?!(?:custom|onetomany|manytomany|atom|tomcat|tomorrow|automatic)b)[a-z]*tom[a-z]*b

我使用了一个词边界(b)而不是锚(^),所以它会在任何地方找到这个词,而不仅仅是在开头。在末尾添加另一个b确保它只匹配完整的单词。

前导子表达式末尾的b对过滤后的单词执行相同的操作。例如,它不会匹配automatic,但它匹配automatically

一旦forward通过,[a-z]*tom[a-z]*b匹配一个包含tom的单词(或者更准确地说,一个连续的字母序列)。我做了很多简化的假设,这样我可以集中精力在技术上。最重要的是,如果您的"words"可以包含非单词字符,如连字符(-)或撇号('), [a-z]*b可能不够好。

最新更新