猿问

正则表达式:如何用出现 n 次的子字符串替换字符串

作为前提,我有一个 HTML 文本,其中包含一些<ol>元素。它们有一个start属性,但我使用的框架无法在 PDF 转换期间解释它们。所以,我试图应用的技巧是在开始时添加一些不可见的<li>元素。


例如,假设这个输入文本:


<ol start="3">

   <li>Element 1</li>

   <li>Element 2</li>

   <li>Element 3</li>

</ol>

我想产生这样的结果:


<ol>

   <li style="visibility:hidden"></li>

   <li style="visibility:hidden"></li>

   <li>Element 1</li>

   <li>Element 2</li>

   <li>Element 3</li>

</ol>

因此,将 n-1 个不可见元素添加到有序列表中。但是我无法以通用的方式从 Java 中做到这一点。


假设示例中的确切情况,我可以这样做(使用replace,所以 - 老实说 - 没有正则表达式):


htmlString = htmlString.replace("<ol start=\"3\">",

            "<ol><li style=\"visibility:hidden\"></li><li style=\"visibility:hidden\"></li>");

但是,显然,它只适用于“start=3”的情况。我知道我可以使用组来提取“3”,但是如何将它用作“变量”来指定字符串<li style=\"visibility:hidden\"></li>n-1 次?感谢您的任何见解。


ibeautiful
浏览 175回答 3
3回答

紫衣仙女

从 Java 9 开始,有一种Matcher.replaceAll方法将回调函数作为参数:String text = "<ol start=\"3\">\n\t<li>Element 1</li>\n\t<li>Element 2</li>\n\t<li>Element 3</li>\n</ol>";String result = Pattern&nbsp; &nbsp; &nbsp; &nbsp; .compile("<ol start=\"(\\d)\">")&nbsp; &nbsp; &nbsp; &nbsp; .matcher(text)&nbsp; &nbsp; &nbsp; &nbsp; .replaceAll(m -> "<ol>" + repeat("\n\t<li style=\"visibility:hidden\" />",&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Integer.parseInt(m.group(1))-1));&nbsp; &nbsp; &nbsp;&nbsp;对于repeat字符串,您可以从这里开始使用技巧,或者使用循环。public static String repeat(String s, int n) {&nbsp; &nbsp; return new String(new char[n]).replace("\0", s);}之后result是:<ol>&nbsp; &nbsp; <li style="visibility:hidden" />&nbsp; &nbsp; <li style="visibility:hidden" />&nbsp; &nbsp; <li>Element 1</li>&nbsp; &nbsp; <li>Element 2</li>&nbsp; &nbsp; <li>Element 3</li></ol>&nbsp; &nbsp;如果您坚持使用旧版本的 Java,您仍然可以分两步进行匹配和替换。Matcher m = Pattern.compile("<ol start=\"(\\d)\">").matcher(text);while (m.find()) {&nbsp; &nbsp; int n = Integer.parseInt(m.group(1));&nbsp; &nbsp; text = text.replace("<ol start=\"" + n + "\">",&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "<ol>" + repeat("\n\t<li style=\"visibility:hidden\" />", n-1));}由 Andrea ジーティーオー 更新:我修改了上面的(很棒的)解决方案,以包含<ol>具有多个属性的内容,以便它们的标签不以start(例如,<ol>带有字母, as <ol start="4" style="list-style-type: upper-alpha;">)结尾。这用于replaceAll整体处理正则表达式。//Take something that starts with "<ol start=", ends with ">", and has a number in betweenMatcher m = Pattern.compile("<ol start=\"(\\d)\"(.*?)>").matcher(htmlString);while (m.find()) {&nbsp; &nbsp; int n = Integer.parseInt(m.group(1));&nbsp; &nbsp; htmlString = htmlString.replaceAll("(<ol start=\"" + n + "\")(.*?)(>)",&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "<ol $2>" + StringUtils.repeat("\n\t<li style=\"visibility:hidden\" />", n - 1));}

吃鸡游戏

你不能使用正则表达式来做到这一点,或者即使你找到了一些技巧来做到这一点,这也将是一个次优的解决方案..正确的方法是使用 HTML 解析库(例如Jsoup),然后将<li>标记作为子项添加到<ol>,特别是使用Element#prepend方法。(使用 Jsoup,您还可以读取start属性值以计算要添加的元素数量)
随时随地看视频慕课网APP

相关分类

Java
我要回答