在String上运行多个正则表达式模式

假设我有一个List和一个空的List ,这是处理将String中的单词变成Pattern对象的最佳方法;

 for(String word : stringList) { patterns.add(Pattern.compile("\\b(" + word + ")\\b); } 

然后在以后的字符串上运行它;

 for(Pattern pattern : patterns) { Matcher matcher = pattern.matcher(myString); if(matcher.matches()) { myString = matcher.replaceAll("String[$1]"); } } 

replaceAll位只是一个例子,但是当我使用它时,大部分时间都会使用$ 1。

有更有效的方法吗? 因为我觉得这有点笨重。 顺便说一句,我在列表中使用80个字符串,虽然使用的字符串是可配置的,所以不会总是这么多。

这是一个有点过时的filter,所以我会让你假设列表中的单词,

输入的一个例子是"You're a " ,这个词的输出将是"You're a *****" ,虽然情况可能并非总是如此,在某些时候我可能是从HashMap读取HashMap其中键是捕获组,值是替换。

例:

 if(hashMap.get(matcher.group(1)) == null) { // Can't test if \ is required. Used it here for safe measure. matcher.replaceAll("\*\*\*\*"); } else { matcher.replaceAll(hashMap.get(matcher.group(1)); } 

您可以使用|替换将这些模式连接在一起 :

 Pattern pattern = Pattern.compile("\\b(" + String.join("|",stringList) + ")\\b"); 

如果您不能使用Java 8,那么不要使用String.join方法,或者如果您需要转义单词以防止其中的字符被解释为正则表达式元字符,则需要使用手动循环构建此正则表达式:

 StringBuilder regex = new StringBuilder("\\b("); for (String word : stringList) { regex.append(Pattern.quote(word)); regex.append("|"); } regex.setLength(regex.length() - 1); // delete last added "|" regex.append(")\\b"); Pattern pattern = Pattern.compile(regex.toString()); 

要对不同的单词使用不同的替换,可以使用此循环应用模式:

 Matcher m = pattern.matcher(myString); StringBuilder out = new StringBuilder(); int pos = 0; while (m.find()) { out.append(myString, pos, m.start()); String matchedWord = m.group(1); String replacement = matchedWord.replaceAll(".", "*"); out.append(replacement); pos = m.end(); } out.append(myString, pos, myString.length()); myString = out.toString(); 

您可以按照自己喜欢的方式查找匹配单词的替换。 该示例生成与匹配单词长度相同的替换字符串。

如果你做同样的事情,无论匹配什么word ,你可以用你的单词组成一个大的“OR”表达式,并使用单个模式,如下所示:

 \\b(||...|)\\b 

其中应该用循环中的单词替换:

 StringBuilder res = new StringBuilder("\\b("); boolean first = true; for(String word : stringList) { if (!first) { res.append("|"); } else { first = false; } res.append(word); } res.append(")\\b"); Pattern p = Pattern.compile(res.toString()); 

注意:此解决方案假定单词没有正则表达式元字符。

来自Boann的Idee已经很好了。 但是例如对于logfiltering我有一个很大的filter列表,那里的文本与正则表达式匹配,我需要知道什么filter匹配。 对于我编码其他filter,如模块,代码,级别等也作为正则表达式。 如果有匹配,我会检查哪个组匹配。

1)所以每行只检查一次。

2)由于所有正则表达式都构建在一个匹配器中,因此每个char只检查一个。

这是从N(条件数)到接近1(几乎任何数量的滤波器都是常数)的极大改进。

 public static void main(final String[] argc) throws Throwable { Config c; try(InputStream s = new FileInputStream("webapp/WEB-INF/logScanConfig.xml")) { c = (Config) JAXBContext.newInstance(Config.class).createUnmarshaller().unmarshal(s); } final LineContext[] a = c.rules.toArray(new LineContext[c.rules.size()]); final StringBuilder regex = new StringBuilder(); for(int i=0;i0) regex.append("|"); regex.append(p); } final Pattern pattern = Pattern.compile(regex.toString(), Pattern.DOTALL); final Matcher m = pattern.matcher("ISS ; 0025 ; 0008 ; I ; State Manager started"); if(!m.matches()) { System.out.println("Not Found"); } else { System.out.println("GroupCount: "+m.groupCount()+" A["+a.length+"]"); for(int i=1;i<=m.groupCount();i++) { if(null != m.group(i)) { System.out.println("GROUP["+(i-1)+"]: "+m.group(i)); System.out.println(a[i-1]); } } } } } 

这是logScanConfig.xml的示例

   http://private.3:80/fetch/log http://private.4:80/fetch/log http://private.5:80/fetch/log   .*ORA-27101: shared memory realm does not exist.* Insufficient memory .*