【问题标题】:Java change text between two substringsJava 在两个子字符串之间更改文本
【发布时间】:2014-05-15 22:02:57
【问题描述】:

假设我有这个字符串:

String s = "random text blah blah <change>hello</change> more random text <change>hey</change> ..";

我想更改 &lt;change&gt;&lt;/change&gt; 元素之间的值(我想对它们进行编码或解码,这只是本例中的一个示例,请注意,要对这些值进行编码,我需要该值标签之间(更改之前)本身也是如此)。

最好的方法是什么? 我正在考虑使用 s.replaceAll() 函数,但我不确定如何在此示例中使用它。

我不能只使用 XML 解析器,因为标签之间的文本可能包含一些特殊字符,如 ,这会在使用 XML 解析器时导致错误。

我正在使用 Java。

【问题讨论】:

  • 它看起来像是 XML 解析器的工作,而不是正则表达式。
  • 是的,我在帖子中忘记说的是,标签之间可能存在一些 字符,在使用 XML 解析器时会导致一些错误

标签: java string


【解决方案1】:

由于您声称这不是有效的 XML 文档,您可以尝试使用正则表达式。要使用新版本替换已建立的值,您可以使用 Matcher 类中的 appendReplacementappendTail

  • appendReplacement 用新版本替换已建立的值。您决定如何更换它。
  • appendTail 将上次匹配后的部分添加到缓冲区。

要在 &lt;change&gt;&lt;/change&gt; 之间找到匹配项,您可以使用 &lt;change&gt;(.*?)&lt;/change&gt; 正则表达式 - 如果您希望点表示所有字符(包括像 \n 这样的行分隔符),您应该使用来自 PatternDOTALL 标志.

演示:

String input = "random text blah blah <change>hello</change> more random text <change>hey</change> ..";
StringBuffer sb = new StringBuffer();

Pattern p = Pattern.compile("<change>(.*?)</change>",Pattern.DOTALL);
Matcher m = p.matcher(input);

while(m.find()){
    String valueFromTags = m.group(1);
    m.appendReplacement(sb, valueFromTags.toUpperCase());
    //                                    ^^^^^^^^^^^^^
    // you decide what to put as replacement of original value
    // toUpperCase is just example
}
m.appendTail(sb);

String result = sb.toString();
System.out.println(result);

输出:

random text blah blah HELLO more random text HEY ..

【讨论】:

    【解决方案2】:

    您可以使用正则表达式,但它有点慢。

    String newString = s.replaceAll("(?<=<change>).+?(?=<\\/change>)", "Your new string");
    

    这意味着您可以在更改位中添加额外的 字符,它仍然可以正常工作。

    编辑:如果你也想使用原词,你可以使用这个:

        String regexPattern = "(?<=<change>).+?(?=<\\/change>)";
        String originalString = "random text blah blah <change>hello</change> more random text <change>hey</change> ..";
    
        Pattern pattern = Pattern.compile(regexPattern);
        Matcher matches = pattern.matcher(originalString);
    
        if (matches.find()){
            String originalText = matches.group(0);
            String t = originalString.replaceAll(regexPattern, originalText + " whatever you want to add");
            System.out.println(t);
        }
        else {
            System.out.println("No matches found");
        }
    

    【讨论】:

    • 问题是我需要 标签之间的子字符串来生成字符串来替换它
    【解决方案3】:

    您需要使用 XML 表示法吗?

    你也可以使用@change

    【讨论】:

      【解决方案4】:

      有趣的谜题。

      假设您想更改标签:

      public class Test
      {
          public static void main(String[] args)
          {
              String s = "random text blah blah <change>hello</change> more random text <change>hey</change> ..";
              System.out.println("BEFORE:"+s);
              System.out.println("AFTER :"+replace(s, "HI", "HELLO"));
          }
      
          private static String replace(String source, String ...replace)
          {
              if (source == null)
                  return null;
              // ... more checks here
              int index=0, next, m=0;
              do
              {
                  index = source.indexOf("<change>", index);
                  next = source.indexOf("</change>", index)+"</change>".length();
                  if (index>0)
                  {
                      source = source.substring(0, index) + replace[m] + source.substring(next);
                      m++;
                  }
              }
              while (index>0);
              return source;
          }
      
      }
      

      输出将是

      BEFORE:random text blah blah <change>hello</change> more random text <change>hey</change> ..
      AFTER :random text blah blah HI more random text HELLO ..
      

      【讨论】:

        【解决方案5】:

        这可能不是个好主意

        寻找出现 > 并替换它们。假设字符串中没有广义的“”

        String s = "random text blah blah <change>hello</change> more random text <change>hey</change> .."
         String formatted = s.replaceAll("\\>", "><").replaceAll("\\<","/><");
        

        【讨论】:

          【解决方案6】:

          这是一个使用正则表达式的解决方案:

              public static void main(String[] args) {
                  final String SIMPLE_TAG_REGEX = "<(.+?)>(.+?)</(.+?)>";
                  final Pattern PATTERN = Pattern.compile(SIMPLE_TAG_REGEX);
          
                  final String s = "hello <foo>bar</foo> world, <lorem>ipsum</lorem>";
                  final Matcher matcher = PATTERN.matcher(s);
                  while (matcher.find()) {
                      final String startTag = matcher.group(1);
                      final String content = matcher.group(2);
                      final String endTag = matcher.group(3);
                      System.out.println(startTag + ", " + endTag + ": " + content);
                  }
              }
          

          打印出来:

              foo, foo: bar
              lorem, lorem: ipsum
          

          请检查startTag.equals(endTag)。正则表达式在理论上(和实践:) 中无法做到这一点!

          【讨论】:

            【解决方案7】:

            这是一种方法:

                String s = "random text blah blah <change>hello</change> more random text <change>hey</change> .."
                String formatted = s.replaceAll("hello", "YOUR CHANGE HERE");
                formatted = s.replaceAll("hey", "YOUR CHANGE HERE");
            

            或者您可以在全部替换中利用正则表达式:

            编辑:

                String s = "random text blah blah <change>hello</change> more random text <change>hey</change> ..";
                String formatted = s.replaceAll("<change>(\\w)+</change>", "YOUR CHANGE HERE");
                System.out.println(formatted);
            

            【讨论】:

            • 这个问题是标签之间的文本每次都可能不同
            • 但是为了用文本本身的编码文本替换标签之间的文本,我也需要两个标签之间的值
            • 如果你想评估标签中的内容,那么在这种情况下,模式和匹配器类是要走的路。如果你使用我给出的正则表达式,你会向匹配器询问 group(1) 的内容,然后你会相应地替换字符串。
            • (\\w)+ 会将比赛中的最后一个字母放在第 1 组中。您可能想要(\\w+)
            猜你喜欢
            • 1970-01-01
            • 2020-06-02
            • 2012-05-14
            • 1970-01-01
            • 1970-01-01
            • 2017-03-17
            • 2015-04-10
            • 1970-01-01
            相关资源
            最近更新 更多