我想替换不在引号之间的单词。
应该如何工作:
“英雄”——不变
“你是超级英雄”——不变
我是英雄 - 改变
你是超级英雄 - 改变
我试过了
word = word.replaceAll("(?!\")(.*)hero(.*)(?!\")","$1 zero $2")
- 但它不起作用
这个正则表达式应该适合你:
hero(?=(?:(?:[^\"]*\"){2})*[^\"]*$)
说明:
这基本上意味着匹配文字文本(hero
),如果它后跟偶数个双引号,换句话说,如果它在双引号之外,则匹配所需的文本。
测试:
String str = "hero \"dont-hero\"";
String repl = str.replaceAll("hero(?=(?:(?:[^\"]*\"){2})*[^\"]*$)", "FOO");
//repl = FOO "dont-hero"
你的问题不清楚。您想处理任意数量的嵌套引号吗?如果是这样,怎么办?例如,您希望以下输入发生什么?
I hate it when people say "you are such a "hero"!"
“英雄”这个词在引号里吗?或者是短语“you are such a”用引号括起来,然后是未引用的单词“hero”,然后是“!” 在引号?
但即使是更简单的情况
"hello" said the boring old "cat", are you really a "hero"?
使用正则表达式可能无法实现,至少不是以使其值得的理智方式实现。
接受的答案以完全不直观的方式失败
I will be your "hero" baby! O"RLY?
你为什么不用一些代码来解析字符串呢?
我觉得以下是比使用正则表达式更好的选择:
class Main {
public static String replace(String str, String origstr, String newstr) {
StringBuilder result = new StringBuilder();
int lastIdx = 0;
boolean inquotes = false;
for (int i = 0; i < str.length(); i++) {
if (str.charAt(i) == '"') {
if (inquotes) {
inquotes = false;
result.append(str.substring(lastIdx, i+1));
} else {
result.append(str.substring(lastIdx, i+1).replace(origstr, newstr));
inquotes = true;
}
lastIdx = i+1;
}
}
result.append(str.substring(lastIdx, str.length()).replace(origstr, newstr));
return result.toString();
}
public static void main (String[] args) throws java.lang.Exception {
System.out.println(replace("", "change", "___"));
System.out.println(replace("\"dont-change\"", "change", "___"));
System.out.println(replace("\"change", "change", "___"));
System.out.println(replace("simple: change", "change", "___"));
System.out.println(replace("simple2: \"dont-change\"", "change", "___"));
System.out.println(replace("change \"dont-change\"\"", "change", "___"));
System.out.println(replace("change \"dont-change\"", "change", "___"));
System.out.println(replace("\"dont-change\" change", "change", "___"));
}
}
一种使用正则表达式的方法。
这个想法是在我放入捕获组的目标词之前匹配引号之间的所有子字符串。然后使用捕获组偏移量,我替换包含目标单词的子字符串。
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class quotyquot {
public static void main(String[] args) {
String s = "I am super hero here and now\n"
+"Superman is an incredible hero\n"
+"I am super \"hero\" here and now\n"
+"\"I am super hero here and now\"";
String t = "hero"; // target
String r = "zero"; // replacement
Integer d = r.length() - t.length();
Integer o = 0; // offset
Pattern p = Pattern.compile("\"[^\"]*\"|(" + t + ")");
Matcher m = p.matcher(s);
while (m.find()) {
if (m.group(1)!=null) {
s= s.substring(0, m.start() - o) + r + s.substring(m.end() - o);
o -= d;
}
}
System.out.println(s);
}
}
使用拆分的另一种方式:
String t = "hero"; // target
String r = "zero"; // replacement
int c=0; // switch
String[] pi = s.split("(?=hero|\")|(?<=hero|\")");
String result = "";
for (int i=0; i<pi.length;i++) {
if (c==0 && pi[i].equals(t))
pi[i]=r;
else if (pi[i].equals("\""))
c = 1 - c;
result += pi[i];
}
System.out.println(result);