java - 如何在 String.replaceAll 中使用 RegEx 在搜索和替换时忽略中间字符

标签 java regex java-8

我必须在 testFile.xml 中搜索每个单词“abc”+ 7 个不重要的数字+“myOldWord”以更改为一些新的而不用担心里面的数字。会有几个“xxx9999999myOldWorld”。如何使用正则表达式找到“abc1234567myOldWorld”并仅将 myOldWorld 替换为 newWorld?我不能只从 myOldWorld 交换到 newWord,因为前三个字符必须在搜索条件中使用,并且必须忽略它们之间未知的 7 个长度。

其他示例。假设我有新世界“aaaOtherNewWord”来替换“aaa9999999OtherOldWord”(搜索时我不知道数字,并且有几个数字不同)。 假设 testFile.xml 中有三个旧单词:aaa1234567OTHEROLDWORD、aaa9876543otheroldword 和 bbb9876543otheroldword,我想执行replaceAll 并得到结果:aaa1234567OtherNewWord 和 aaa9876543OtherNewWord 分别,但 bbb9876543otheroldword 不会改变,因为前 3 个数字与搜索条件不匹配.

我在下面编写了代码,并成功地在搜索时忽略了大小写,但我必须忽略数字,而且我不知道如何使用正则表达式来做到这一点。

Path path = Paths.get("C:\\testFolder\\testFile.xml");
Charset charset = StandardCharsets.UTF_8;
String content = new String(Files.readAllBytes(path), charset);
content = content.replaceAll("(?i)" + oldWord, newWord);

注意:我使用的是 Java 8。

整个测试是:

//C:\test.xml

<?xml version="1.0" encoding="UTF-8"?>
<c:bps xmlns:c="CertainApp">
<c:bp name="ProductPortfolio" id="myProdPort">

  <!-- must result in ABC1234567MyCompanyWORDProductSubproduct-->
  <c:message type="ABC1234567MyCompanyWorDProductSubproduct" /> 

  <!-- must result in ABC0987654MyCompanyWORDProductSubproduct-->
  <c:message type="ABC0987654MyCompanyWoRdProductSubproduct" />

  <!-- must result in XYZ1234567MyCompanywordproductSubproduct-->
  <c:message type="XYZ1234567MyCompanywOrdproductSubproduct" />

  <!-- nothing changed in next two-->
  <c:message type="XYZ1234567MyCompanyAnyThingproductSubproduct" />
  <c:message type="XYZ0987654MyCompanyAnyThingproductSubproduct" />
</c:bps>  

//C:\defaults_test包含两个文件

ABCMyCompanyWORDproductSubproduct.xml  //here the “word” is uppercase and starts with ABC

XYZMyCompanywordproductSubproduct.xml  //here the “word” is lowercase and starts with XYZ

public class ReadICTTDefaultFolder {
       public static void replaceFileString(String first3letters, String word)  {
                     Path path = Paths.get("C:\\test.xml");
                     Charset charset = StandardCharsets.UTF_8;
                     try{
                           String content = new String(Files.readAllBytes(path), charset);
                           content = content.replaceAll("((?i)" + first3letters + "\\d{7})" + word, "$1"+word);
                           Files.write(path, content.getBytes(charset));
                     }
                     catch(Exception e){
                     }
       }

       public static void main(String[] args) {

           File actual = new File("C:\\ defaults_test");
           File list[] = actual.listFiles();

           for(int i=0; i<list.length; i++){
               String substring = list[i].getName().substring(0, list[i].getName().indexOf("."));

               if(list[i].isFile() && substring.toUpperCase().contains("WORD")){
                      replaceFileString(substring.substring(0,3), substring.substring(3));

               }
           }
}

最佳答案

content = content.replaceAll("(abc\\d{7})" + oldWord, "$1"+newWord);

您可以在替换字符串中通过 $n 引用组,其中 n 是组编号。

正则表达式部分 \\d{7} 恰好匹配七个数字(不要将其与数字混淆)。

也可以使用肯定的后向断言来选择正确的 oldWord:

      replaceAll( "(?<=abc\\d{7})" + oldWord, newWord )

然后你就不需要 1 美元了。

稍后

现在我看到了整个困惑,其中“(?i)”是必不可少的,我应该添加一个选项字符串必须写在括号的正确嵌套级别:

 ...replaceAll("(?i)(" + prefix + "\\d{7})" + oldWord, "$1"+newWord);

 ...replaceAll("((?i)" + prefix + "\\d{7})" + oldWord, "$1"+newWord);

这会将忽略大小写的匹配限制为前缀。由于前缀也许应该完全匹配,所以最好写

 ...replaceAll("(" + prefix + "\\d{7})(?i)" + oldWord, "$1"+newWord);

看起来,oldWord 和 newWord 除了大小写外都是相同的,您也可以使用

 ...replaceAll("(" + prefix + "\\d{7})(?i)" + word, "$1" + word);

关于java - 如何在 String.replaceAll 中使用 RegEx 在搜索和替换时忽略中间字符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27866333/

相关文章:

Java如何动态读取日期

jquery - 接受文件类型 Blueimp 文件上传

Java正则表达式拆分文本(分隔符和顺序都可能未知)

java - Java,嵌套循环,提高性能

java - 我需要迭代和计算 Nested Map<key, someObjectArray[]>

lambda - 将Java Lambda转换为Kotlin

java - SQL 仅替换为一行中的前两列

java - 使用装饰器模式时如何保留接口(interface)?

java - 音频播放不正常

javascript - RegExp.exec 不返回全局结果