为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

ibeautiful 2021-09-03 13:56:55
作为前提,我有一个 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 次?感谢您的任何见解。
查看完整描述

3 回答

?
紫衣仙女

TA贡献1839条经验 获得超15个赞

从 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

        .compile("<ol start=\"(\\d)\">")

        .matcher(text)

        .replaceAll(m -> "<ol>" + repeat("\n\t<li style=\"visibility:hidden\" />", 

                                         Integer.parseInt(m.group(1))-1));      

对于repeat字符串,您可以从这里开始使用技巧,或者使用循环。


public static String repeat(String s, int n) {

    return new String(new char[n]).replace("\0", s);

}

之后result是:


<ol>

    <li style="visibility:hidden" />

    <li style="visibility:hidden" />

    <li>Element 1</li>

    <li>Element 2</li>

    <li>Element 3</li>

</ol>   

如果您坚持使用旧版本的 Java,您仍然可以分两步进行匹配和替换。


Matcher m = Pattern.compile("<ol start=\"(\\d)\">").matcher(text);

while (m.find()) {

    int n = Integer.parseInt(m.group(1));

    text = text.replace("<ol start=\"" + n + "\">", 

            "<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 between

Matcher m = Pattern.compile("<ol start=\"(\\d)\"(.*?)>").matcher(htmlString);

while (m.find()) {

    int n = Integer.parseInt(m.group(1));

    htmlString = htmlString.replaceAll("(<ol start=\"" + n + "\")(.*?)(>)",

            "<ol $2>" + StringUtils.repeat("\n\t<li style=\"visibility:hidden\" />", n - 1));

}


查看完整回答
反对 回复 2021-09-03
?
吃鸡游戏

TA贡献1829条经验 获得超7个赞

你不能使用正则表达式来做到这一点,或者即使你找到了一些技巧来做到这一点,这也将是一个次优的解决方案..

正确的方法是使用 HTML 解析库(例如Jsoup),然后将<li>标记作为子项添加到<ol>,特别是使用Element#prepend方法。(使用 Jsoup,您还可以读取start属性值以计算要添加的元素数量)


查看完整回答
反对 回复 2021-09-03
  • 3 回答
  • 0 关注
  • 172 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信