Java正则表达式组替换,无需匹配组偏移量操作
对于非常特定类型的子序列,我经常会遇到诸如从XHTML文档中删除标记之类的要求。(不允许使用Java正则表达式组替换,无需匹配组偏移量操作,java,regex,Java,Regex,对于非常特定类型的子序列,我经常会遇到诸如从XHTML文档中删除标记之类的要求。(不允许使用String.replaceAll())。通常它的模式是${randomTextandHtmlRorJavaScript},但一个常量是它总是一个带有大量垃圾的任意标记,后跟它的结束标记。没有标签嵌套 我的问题是,除了手动操作Matcher对象之外,是否有人知道更高级别的抽象。在过去,我做过这样的替换: 将问题视为数组副本,其中我使用StringBuilder对象并使用Matcher.start(int)
String.replaceAll()
)。通常它的模式是${randomTextandHtmlRorJavaScript},但一个常量是它总是一个带有大量垃圾的任意标记,后跟它的结束标记。没有标签嵌套
我的问题是,除了手动操作Matcher
对象之外,是否有人知道更高级别的抽象。在过去,我做过这样的替换:
StringBuilder
对象并使用Matcher.start(int)
和Matcher.end(int)
方法不从输入String
复制目标组。这是可行的,但感觉像是C,而不是Javamatch1.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
,因为JavaString
s是不可变的。如果您想随后执行另一个替换,则需要将reset()
匹配器
重置为其新输入。是的,Matcher.replaceAll()
会更改匹配器的状态,但您认为如果不是这样,以后可以对其执行什么操作<代码> RetryApple()/代码>将产生一个结果(新的<代码>字符串< /代码>),其中“<代码>匹配器< /代码>模式的每一个发生都被替换,据我所知,您需要的是什么。您还可以考虑一次处理输入一个匹配,使用<代码> AppEdRePayStices()/<代码>,用<代码> AppEdTead()结束。
。这更灵活,而且它确实避免了在每个步骤从一开始就重新划分字符串。我编辑了我的答案以提及这些。