Regex: comment remplacer une chaîne avec n occurrences d'une sous-chaîne

Andrea:

En principe, j'ai un texte HTML, avec quelques <ol>éléments. Celles - ci ont un startattribut, mais le cadre que je utilise est pas capable de les interpréter lors d' une conversion de PDF. Alors, le truc que je suis en train d'appliquer est d'ajouter un certain nombre d'invisibles <li>éléments au début.

À titre d'exemple, supposons que ce texte d'entrée:

<ol start="3">
   <li>Element 1</li>
   <li>Element 2</li>
   <li>Element 3</li>
</ol>

Je veux produire ce résultat:

<ol>
   <li style="visibility:hidden"></li>
   <li style="visibility:hidden"></li>
   <li>Element 1</li>
   <li>Element 2</li>
   <li>Element 3</li>
</ol>

Donc, en ajoutant n-1 éléments invisibles dans la liste ordonnée. Mais je ne suis pas en mesure de le faire à partir de Java de manière généralisée.

En supposant le cas exact dans l'exemple, je pourrais le faire ( en utilisant replace, donc - pour être honnête - sans regex):

htmlString = htmlString.replace("<ol start=\"3\">",
            "<ol><li style=\"visibility:hidden\"></li><li style=\"visibility:hidden\"></li>");

Mais, de toute évidence, il applique juste le cas avec « start = 3 ». Je sais que je peux utiliser des groupes pour extraire le « 3 », mais comment puis - je l' utiliser comme une « variable » pour spécifier la chaîne <li style=\"visibility:hidden\"></li>n-1 nombre de fois? Merci pour toute perspicacité.

tobias_k:

Depuis Java 9, il y a une Matcher.replaceAllméthode prenant une fonction de rappel comme paramètre:

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));      

Pour repeatla chaîne , vous pouvez prendre l'affaire d' ici , ou utiliser une boucle.

public static String repeat(String s, int n) {
    return new String(new char[n]).replace("\0", s);
}

, Après resultest la suivante :

<ol>
    <li style="visibility:hidden" />
    <li style="visibility:hidden" />
    <li>Element 1</li>
    <li>Element 2</li>
    <li>Element 3</li>
</ol>   

Si vous êtes coincé avec une ancienne version de Java, vous pouvez toujours et à remplacer en deux étapes.

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));
}

Mise à jour par Andrea Gee thé O:

Je modifié la (grande) solution ci - dessus pour inclure également <ol>qui ont plusieurs attributs, de sorte que leur étiquette ne se termine pas avec start( par exemple, <ol>avec des lettres, comme <ol start="4" style="list-style-type: upper-alpha;">). Celui - ci utilise replaceAllpour traiter avec regex dans son ensemble.

//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));
}

Je suppose que tu aimes

Origine http://43.154.161.224:23101/article/api/json?id=119980&siteId=1
conseillé
Classement