【问题标题】:SubString replacement in text文本中的子字符串替换
【发布时间】:2014-09-08 17:55:45
【问题描述】:

我想替换文本中除第一个字符串之外所有出现的字符串。 例如:

输入:示例 [2] 这是一个示例文本。这是一个示例文本。这是一个示例文本。

替换词:示例(简单)

输出:示例 [2] 这是一个示例文本。这是一个简单文本。这是一个简单文本。

在字符串函数中我看到的是replace、replaceAll、replaceFirst。

我应该如何处理这种情况。

提前致谢。

【问题讨论】:

    标签: java regex replace substring


    【解决方案1】:

    您可以使用此正则表达式进行搜索:

    ((?:\bsample\b|(?<!^)\G).*?)\bsample\b
    

    这是替换:

    $1simple
    

    RegEx Demo

    Java 代码:

    String r = input.replaceAll("((?:\\bsample\\b|(?<!^)\\G).*?)\\bsample\\b", "$1simple");
    

    【讨论】:

    • 是的,当然。 \G 匹配行首或前一个匹配的结尾。因此,此正则表达式在文字 sampleend of the previous match 到下一次出现 sample 之间找到字符串,并将其捕获为组 #1。然后它会在它旁边找到一个文字sample。在替换中,它使用反向引用 $1simple 将除第一个 sample 之外的所有内容替换为 simple
    • 谢谢.. 但是示例和简单在文本中并不固定。文本随不同的文件而变化。
    • @user2832203:您可以使用任何其他搜索词代替代码中的sample 或任何其他词代替simple
    • @vks:我刚刚在之前对AvinashRaj的评论中解释了\G
    • 在 python regex 或 pCRE 中是否可以使用 \G?
    【解决方案2】:
    • replaceAllreplace 将替换所有子字符串(它们之间的区别在于 replaceAll 使用正则表达式作为参数,而 replace 使用文字)。
    • replaceFirst 将仅替换与您要查找的模式匹配的第一个子字符串。

    你能做的是

    • 使用indexOf(String str, int fromIndex)方法确定第一个和第二个sample字的索引,
    • 然后在第二个sample 的索引上substring(int beginIndex) 获取您希望允许替换的字符串的一部分
    • 并在这部分调用您的 replace 方法
    • 替换完成后,您可以连接不应更改的部分(在第二个 sample 单词的索引之前)和替换值的部分

    其他解决方案是使用appendReplacementappendTail 形式Matcher 类,并在找到第二个sample 单词后使用替换值。它的代码看起来像

    String yourString = "Example [2] This is a sample text. This is a sample text. This is a sample text.";
    Pattern p = Pattern.compile("sample", Pattern.LITERAL);
    Matcher m = p.matcher(yourString);
    StringBuffer sb = new StringBuffer();
    boolean firstWordAlreadyFound = false;
    while (m.find()) {
        if (firstWordAlreadyFound) {
            m.appendReplacement(sb, "sImple");
        } else {
            m.appendReplacement(sb, m.group());
            firstWordAlreadyFound = true;
        }
    }
    m.appendTail(sb);
    String result = sb.toString();
    System.out.println(result);
    

    输出:

    Example [2] This is a sample text. This is a sImple text. This is a sImple text.
    

    【讨论】:

    • 这对我不起作用...整个场景如下:替换文本在 hashmap 中,key 作为文本中要替换的字符串。我可以更换所有的钥匙..但我只需要更换除第一个以外的所有钥匙。我正在遍历hashmap,然后替换。我在 hashmap 迭代中尝试了你的代码。
    • @user2832203 嗯,这是一种重要的信息,应该从一开始就放在原始问题中。在这种情况下,您需要创建能够匹配 HashMap 中的任何键的模式,但创建这样的模式可能会很棘手:您必须以从最详细到不太详细的方式对键进行排序,以避免出现模式将是fo|foo,因为对于字符串foofoo 中的这个正则表达式,您只会匹配fo 两次,因为在正则表达式中fo|foo fo 具有更高的优先级,因为它位于左侧并且正则表达式从左到右读取。
    • @user2832203 另外,我们不知道您是否要查找单词或子字符串(name 是否应该与 surname 匹配?)。我看不出有一种方法可以在不使所有答案失去意义的情况下将此问题更改为其他问题,因此请考虑接受其中一个答案作为您在此问题中描述的问题的解决方案,并创建新的答案,您将在其中准确描述您的内容想要做什么(您的输入看起来如何 - 文本和键值映射 - 更详细地了解您想要实现的目标 - 是否有任何潜在的假阳性匹配,例如 surname 中的 name?)。
    【解决方案3】:

    这是一个幼稚的方法:

    public static String replaceAllButFirst(String text, String toReplace, String replacement) {
        String[] parts = text.split(toReplace, 2);
        if(parts.length == 2) {  //Found at least one match
            return parts[0] + toReplace + parts[1].replaceAll(toReplace, replacement);
        } else { //no match found giving original text
            return text;
        }
    }
    
    public static void main(String[] args) {
        String x = "This is a sample test. This is a sample test. This is a sample test";
        System.out.println(replaceAllButFirst(x, "sample", "simple"));
    }
    

    这会给:

    This is a sample test. This is a simple test. This is a simple test
    

    【讨论】:

      【解决方案4】:

      尝试使用substringindexOf 方法将其拆分为两个字符串,然后替换为第二个字符串,最后将两个字符串附加回来

      示例代码:

      String str = "Example [2] This is a sample text. This is a sample text. This is a sample text.";
      
      String findWhat = "sample";
      int index = str.indexOf(findWhat) + findWhat.length();
      
      String temp = str.substring(0, index + 1); // first string
      str = str.substring(index + 1);            // second string
      
      //replace in second string and combine back
      str = temp + str.replace(findWhat, "simple"); // final string
      System.out.println(str); 
      

      将所有内容组合成几个语句:

      int index = str.indexOf(findWhat) + findWhat.length();
      str = str.substring(0, index + 1) + str.substring(index + 1).replace(findWhat, "simple");
      

      【讨论】:

        【解决方案5】:

        在 String 或 StringBuilder 类中没有内置函数可以完全满足您的需求。你需要自己写。这是一个快速的:

            private string ReplaceText(string originalText, string textToReplace, string replacementText)
            {
                string tempText;
                int firstIndex, lastIndex;
        
                tempText = originalText;
                firstIndex = originalText.IndexOf(textToReplace);
                lastIndex = tempText.LastIndexOf(textToReplace);
        
                while (firstIndex >= 0 && lastIndex > firstIndex)
                {
                    tempText = tempText.Substring(0,lastIndex) + replacementText + tempText.Substring(lastIndex + textToReplace.Length);
                    lastIndex = tempText.LastIndexOf(textToReplace);
                }
        
                return tempText;
            }
        

        【讨论】:

          【解决方案6】:

          另一种选择:

          (?<=\bsample\b)(.*?)\bsample\b
          

          和替换:

          $1yourstring
          

          Java 代码:

          String s=input.replaceAll("(?<=\\bsample\\b)(.*?)\\bsample\\b", "$1yourString");
          

          【讨论】:

          • 问题被标记为java。
          猜你喜欢
          • 2014-01-26
          • 2012-03-24
          • 1970-01-01
          • 2012-04-03
          • 2013-07-23
          • 2021-10-05
          相关资源
          最近更新 更多