如何在 String.replaceAll 中使用 RegEx 在搜索和替换时忽略中间字符
how use RegEx in String.replaceAll for ignoring middle characters while searching and replacing
我必须在 testFile.xml 中搜索每个单词 "abc" + 7 个不重要的数字 + "myOldWord" 以更改为一些新的而不用担心里面的数字。会有几个"xxx9999999myOldWorld"。如何找到 "abc1234567myOldWorld" 并使用正则表达式仅将 myOldWorld 替换为 newWorld?我不能只从 myOldWorld 交换到 newWord,因为搜索条件中必须使用前三个字符,并且必须忽略它们之间未知的 7 个长度。
其他例子。假设我有新世界 "aaaOtherNewWord" 来替换 "aaa9999999OtherOldWord" (我在搜索时不知道数字,其中有几个数字不同)。
假设 testFile.xml 中有三个旧词:aaa1234567OTHEROLDWORD、aaa9876543otheroldword 和 bbb9876543otheroldword,我想执行 replaceAll 并获得结果:aaa1234567OtherNewWord 和 aaa9876543OtherNewWord respectvely 但 bbb9876543otheroldword 不会匹配第一个数字,因为第一个数字不会改变搜索条件。
我在下面编码并成功地在搜索时忽略了大小写,但我必须忽略数字而且我不知道如何使用正则表达式来做到这一点。
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);
注:我用的是Java8.
整个测试是:
// 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, ""+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, ""+newWord);
您可以在替换字符串中通过 $n
引用组,其中 n
是组号。
正则表达式部分 \d{7}
恰好匹配七个 数字 (不要将其与数字混淆)。
也可以使用肯定的回顾断言来选择正确的 oldWord:
replaceAll( "(?<=abc\d{7})" + oldWord, newWord )
然后你就不需要这 1 美元了。
以后
现在我看到了整个混乱,其中“(?i)”是必不可少的,我应该补充一点,选项字符串必须写在正确的括号嵌套级别:
...replaceAll("(?i)(" + prefix + "\d{7})" + oldWord, ""+newWord);
和不是
...replaceAll("((?i)" + prefix + "\d{7})" + oldWord, ""+newWord);
这会将忽略大小写的匹配限制为前缀。由于前缀可能应该完全匹配,所以最好写
...replaceAll("(" + prefix + "\d{7})(?i)" + oldWord, ""+newWord);
看来,oldWord和newWord除了大小写是一样的,你也可以使用
...replaceAll("(" + prefix + "\d{7})(?i)" + word, "" + word);
我必须在 testFile.xml 中搜索每个单词 "abc" + 7 个不重要的数字 + "myOldWord" 以更改为一些新的而不用担心里面的数字。会有几个"xxx9999999myOldWorld"。如何找到 "abc1234567myOldWorld" 并使用正则表达式仅将 myOldWorld 替换为 newWorld?我不能只从 myOldWorld 交换到 newWord,因为搜索条件中必须使用前三个字符,并且必须忽略它们之间未知的 7 个长度。
其他例子。假设我有新世界 "aaaOtherNewWord" 来替换 "aaa9999999OtherOldWord" (我在搜索时不知道数字,其中有几个数字不同)。 假设 testFile.xml 中有三个旧词:aaa1234567OTHEROLDWORD、aaa9876543otheroldword 和 bbb9876543otheroldword,我想执行 replaceAll 并获得结果:aaa1234567OtherNewWord 和 aaa9876543OtherNewWord respectvely 但 bbb9876543otheroldword 不会匹配第一个数字,因为第一个数字不会改变搜索条件。
我在下面编码并成功地在搜索时忽略了大小写,但我必须忽略数字而且我不知道如何使用正则表达式来做到这一点。
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);
注:我用的是Java8.
整个测试是:
// 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, ""+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, ""+newWord);
您可以在替换字符串中通过 $n
引用组,其中 n
是组号。
正则表达式部分 \d{7}
恰好匹配七个 数字 (不要将其与数字混淆)。
也可以使用肯定的回顾断言来选择正确的 oldWord:
replaceAll( "(?<=abc\d{7})" + oldWord, newWord )
然后你就不需要这 1 美元了。
以后
现在我看到了整个混乱,其中“(?i)”是必不可少的,我应该补充一点,选项字符串必须写在正确的括号嵌套级别:
...replaceAll("(?i)(" + prefix + "\d{7})" + oldWord, ""+newWord);
和不是
...replaceAll("((?i)" + prefix + "\d{7})" + oldWord, ""+newWord);
这会将忽略大小写的匹配限制为前缀。由于前缀可能应该完全匹配,所以最好写
...replaceAll("(" + prefix + "\d{7})(?i)" + oldWord, ""+newWord);
看来,oldWord和newWord除了大小写是一样的,你也可以使用
...replaceAll("(" + prefix + "\d{7})(?i)" + word, "" + word);