正则表达式改变不​​在“”之间的单词

时间:2013-06-27 21:11:34

标签: java regex

我想替换不在引号之间的单词。

应该如何运作:

“英雄” - 不会改变

“你是超级英雄” - 不改变

我是英雄 - 改变

你是超级英雄 - 改变

我试过

word = word.replaceAll("(?!\")(.*)hero(.*)(?!\")","$1 zero $2") - 但它不起作用

3 个答案:

答案 0 :(得分:1)

这个正则表达式适合你:

hero(?=(?:(?:[^\"]*\"){2})*[^\"]*$)

<强>说明: 这基本上意味着匹配文字文本(hero),如果它后跟偶数个双引号,换句话说,如果它在双引号之外,则匹配所需的文本。

<强>测试

String str = "hero \"dont-hero\"";
String repl = str.replaceAll("hero(?=(?:(?:[^\"]*\"){2})*[^\"]*$)", "FOO");
//repl = FOO "dont-hero"

现场演示:http://ideone.com/BXJxpw

答案 1 :(得分:0)

你的问题不明确。你想处理任意数量的嵌套引号吗?如果是这样,怎么样?例如,您希望通过以下输入实现什么目标?

I hate it when people say "you are such a "hero"!"

这里的引号是“英雄”吗?或者是引号中的“你是这样的”这个短语,后跟未加引号的单词“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", "___"));        
  }
}

答案 2 :(得分:0)

使用正则表达式的方法。

这个想法是匹配我放入捕获组的目标词之前的引号之间的所有子串。然后使用捕获组偏移量,我替换包含目标字的子字符串。

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);
    }
}

使用split的另一种方式:

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);