Java正则表达式组替换,无需匹配组偏移量操作

Java正则表达式组替换,无需匹配组偏移量操作,java,regex,Java,Regex,对于非常特定类型的子序列,我经常会遇到诸如从XHTML文档中删除标记之类的要求。(不允许使用String.replaceAll())。通常它的模式是${randomTextandHtmlRorJavaScript},但一个常量是它总是一个带有大量垃圾的任意标记,后跟它的结束标记。没有标签嵌套 我的问题是,除了手动操作Matcher对象之外,是否有人知道更高级别的抽象。在过去,我做过这样的替换: 将问题视为数组副本,其中我使用StringBuilder对象并使用Matcher.start(int)

对于非常特定类型的子序列,我经常会遇到诸如从XHTML文档中删除标记之类的要求。(不允许使用
String.replaceAll()
)。通常它的模式是${randomTextandHtmlRorJavaScript}

,但一个常量是它总是一个带有大量垃圾的任意标记,后跟它的结束标记。没有标签嵌套

我的问题是,除了手动操作
Matcher
对象之外,是否有人知道更高级别的抽象。在过去,我做过这样的替换:

  • 将问题视为数组副本,其中我使用
    StringBuilder
    对象并使用
    Matcher.start(int)
    Matcher.end(int)
    方法不从输入
    String
    复制目标组。这是可行的,但感觉像是C,而不是Java

  • 执行一个循环,其中我使用开始标记查找第一个标记,并将
    match1.group()
    的结果作为第二个
    Matcher
    的输入,以捕获结束标记,然后使用
    Matcher.replaceFirst()
    处理输入字符串本身中的替换。这有一个缺点,即需要调用
    Matcher.reset()
    强制重新分析。(我只在一次性脚本或输入集很小的情况下使用此选项。)

  • 一个标记上的
    String.split()
    ,替换它,除非与
    match1
    匹配,并使用
    StringBuilder
    重建字符串。对表示结束标记序列的标记运行第二个
    Matcher
    ,并在追加之前执行
    String.replaceAll()

  • 我也尝试过使用
    StringBuilder.deleteCharAt()
    方法,但对于Java这样的语言来说,仍然感觉太低级了

  • 理想的方法签名如下:

    Matcher.replaceGroup(int targetGroup, String pattern, String replacement);
    
    最终,我希望在Java中替换一个正则表达式匹配组,而不需要使用组/数组偏移量

    对于XHTML(或其他XML)文档,一个(更多)更高级别的抽象是XSL转换。它们比正则表达式更具表现力和功能,即使您需要处理内部结构,它们也可以工作

    或者,如果您希望使逻辑更接近Java,那么为什么不在替换字符串中使用反向引用:

    Pattern pat = Pattern.compile("(<p>keep )(stuff I don't want)( this</p>)");
    Matcher m = p.matcher(input);
    
    // Replace matches to the pattern with the same thing less "stuff I don't want":
    String output = m.replaceAll("$1$3");
    
    Pattern pat=Pattern.compile((keep)(我不想要的东西)(this

    )”; 匹配器m=p.Matcher(输入); //将模式的匹配项替换为“我不想要的东西”: 字符串输出=m.replaceAll($1$3”);
    我知道你说过你不能使用
    replaceAll()
    ,但我不清楚你为什么不能通过这种方法完成你在(1)(例如)中描述的内容

    当然,反向引用也适用于
    Matcher.replaceFirst()
    String.replaceAll()
    String.replaceFirst()

    编辑以添加:


    如果您想以迭代方式逐步完成,以便在匹配过程中对其进行更多处理,那么您应该查看
    Matcher.appendReplacement()
    (也可以使用反向引用)和
    Matcher.appendTail()

    问题是一个裸
    字符串。replaceAll()
    与您刚刚完成的工作不同。太好了!这种技术(在大字符串上)是否仍然需要您重置
    匹配器
    ,从而强制重新分析(现在已更改)
    字符串?
    @avgvstvs我不确定我是否理解重置
    匹配器的问题。您可以使用
    replaceAll()
    ,如图所示,全局执行匹配和替换,但结果是不同的
    String
    ,因为Java
    String
    s是不可变的。如果您想随后执行另一个替换,则需要将
    reset()
    匹配器
    重置为其新输入。是的,
    Matcher.replaceAll()
    会更改
    匹配器的状态,但您认为如果不是这样,以后可以对其执行什么操作<代码> RetryApple()/代码>将产生一个结果(新的<代码>字符串< /代码>),其中“<代码>匹配器< /代码>模式的每一个发生都被替换,据我所知,您需要的是什么。您还可以考虑一次处理输入一个匹配,使用<代码> AppEdRePayStices()/<代码>,用<代码> AppEdTead()结束。
    。这更灵活,而且它确实避免了在每个步骤从一开始就重新划分字符串。我编辑了我的答案以提及这些。