9
votes

Comment utiliser les marqueurs de début et de fin de ligne dans Regex pour Java String?

Pourquoi les suivants ne changent-t-il pas le texte pour moi dans Android? XXX

Il renvoie la valeur d'origine sans modification. Je m'attendrais à ce qu'il remplace le centre = test = avec Test

Qu'est-ce que je manque ici ?

EDIT: D'accord, je comprends pourquoi ^ et $ ne fonctionne pas. Le point est que j'ai besoin de quelque chose qui correspond au texte à la fois au début et à la fin d'une ligne, par exemple une ligne qui ne contient que "= un peu de texte =". La plupart des réponses données ne sont pas suffisantes, pour les raisons suivantes:

= (. +) = n'a rien à voir avec les terminaisons de ligne, alors correspond donc à une ligne avec deux = dans celui qui ne sont pas côte à côte.

. * = (. +) =. * correspond à toute la ligne, mais a Le même problème que le précédent

\ n = (. +) = \ n se rapproche, mais ne correspond pas à deux lignes d'une ligne (par exemple, test \ n = test = \ n = test = \ ntest ) Il ne correspond pas également à une instance sur la première ou la dernière ligne

(? <= \ n) = (. +) = (? = \ n) fonctionne presque, mais à nouveau ne correspond pas à une instance sur la première ou la dernière ligne

(? est le seul qui semble correspondre à chaque ligne qui démarre et se termine par = , par exemple, mais 1 $ contient à la fois le remplacement et la chaîne d'origine.

content = content.replaceall ("(? <= (\ n | ^ ^ ^)) = (. +) = (\ n | €))" Grand> 2 $ "); est la seule réponse qui semble faire en réalité faire ce qu'il devrait.


2 commentaires

Cela semble fonctionner: content.replaceall ("(? ")


(? et (? <= \ n) Pouvez-vous expliquer cette syntaxe de regex? Je suis en fait confus par et <=


5 Réponses :


0
votes

Eh bien, comme vous l'avez déjà dit, il s'agit de marqueurs de début / de fin de la regex. ^ n'est pas le début d'une ligne mais de la chaîne entière, également $ est la fin de la chaîne entière.

Essayez de changer l'expression: ^. * = (. +) =. * $ ou laissez ces marqueurs dehors: = (. +) =

Pour faire correspondre le début de la ligne, vous pouvez utiliser ceci: (?: ^ | \ n) = (. *) = . De mes tests en Java Plain, il semble que la pause de la ligne de fuite ne soit pas reconnue, mais cela pourrait être différent dans Android.


1 commentaires

D'accord, je vois ça maintenant; N'y a-t-il aucun moyen de faire correspondre le début et la fin d'une ligne?



3
votes

dans les objets de chaîne Java \ n code> n'est pas considéré comme un début d'une ligne ou une fin d'une ligne. C'est une alimentation en ligne. Pour correspondre à cela, vous devez modifier votre code en

String content = "test\n=test=\n=test=\ntest";
String[] pieces = content.split("[\r\n]");
StringBuilder replaced = new StringBuilder();

for (int i=0; i<pieces.length; i++) {
    String piece = pieces[i].replaceAll("^=(.+)=$", "<size:large>$1</size:large>");
    replaced.append(piece);
    replaced.append('\n');
}


6 commentaires

Cela remplace également les nouvelles lignes du résultat. Vous devrez les ajouter à la chaîne de remplacement.


Je ne suis pas sûr de l'Android ici, mais de mes tests en Java Plain, il semble que le trailing \ n n'est pas reconnu.


@Thomes ne savent pas pourquoi. Ça marche pour moi. Laissez-vous la chaîne d'un fichier ou d'un même objet de chaîne que dans l'exemple? À partir d'un fichier, la regex devra correspondre à \ r ou \ n , pour tenir compte du CRLF.


Merci, c'est ce que j'essaie; Le problème est que cela ne fonctionne pas pour dire test \ n = test = \ n = test = \ ntest - il ne correspond que le premier, pas la deuxième instance.


C'est parce qu'une fois \ n = test = \ n a été assorti, les caractères suivants sont = test = \ n . Il n'y a pas \ n dans le prochain ensemble pour correspondre à la regex.


Oui, je sais, je voulais juste souligner que cette réponse ne fonctionne pas parfaitement pour moi. Voir le commentaire à ma question pour une réponse qui semble fonctionner ...



0
votes

D'accord, je pense avoir une réponse ... Cela semble fonctionner: xxx

n'est-ce pas?

Edit: Ce qui précède ne fonctionne pas , pour une raison quelconque, il copie le texte original et la place après le texte substitué ... Voici ce qu'on a finalement travaillé: xxx


4 commentaires

C'est vague. Le Docs pour motif dire que . peut correspondre ou ne correspond pas à des terminaiseurs de ligne .


Je suppose que le . ne correspond que des terminateurs de ligne si vous définissez motif.dotall , non?


Ouais c'est la raison derrière peut ou non , mais je ne sais toujours pas comment cela s'applique à string.replaceall ; Peut-être que via (? s) dans le motif. Le bit dotall dit que . ne doit pas correspondre à des lignes neuves par défaut.


Sur la base des tests, je peux confirmer que cela ne fonctionne pas par défaut.



4
votes

Le meilleur moyen de faire face à cela est de définir modèle.Multiline code> . En utilisant multiline code>, ^ code> et $ code> correspondra à des lignes séparées à l'aide de \ n code> et de manipulera la même manière Le début de l'entrée et la fin de l'entrée.

à l'aide de string.replaceall code> Vous devez définir ces dans em> le motif à l'aide d'une expression d'indicateur intégré (? m ) code>, pour multiline code>: p> xxx pré>

si vous ne em> pas utiliser multiline code>, vous devez utiliser positif em> lookahead et lookbehind pour le \ n code>, et la regex est compliquée afin de correspondre à la première ligne, et la dernière ligne s'il n'y a pas \ n code> à la fin, par exemple Si notre entrée est la suivante: = test = \ n = test = \ n = test = \ n = test = code>. p>

String pattern = "(?<=(?:^|\n))=(.+)=(?=(?:\n|$))";
content = str.replaceAll(pattern, "<size:large>$1</size:large>");


3 commentaires

En fait, cela ne correspondra pas à la première ou dernière ligne, n'est-ce pas? Lookahead négatif est probablement mieux ...


Je ne vois aucun besoin pour le modificateur UNIX_LINES. En fait, si le texte a des séparateurs de lignes de style DOS ( \ r \ n ), le modificateur (? dm) rendra l'échec du regex, tandis que (? m) seul fonctionne bien.


@Alanmoore tout à fait à propos de Unix_line. J'ai édité la réponse à ne pas conserver sur seulement multiligne. Merci.



10
votes

Votre regex d'origine fonctionne bien si vous activez le mode multiligne, en utilisant (? m) : xxx

maintenant ^ et < Code> $ correspond effectivement aux limites de la ligne.


1 commentaires

Merci, c'était la réponse que je cherchais!