web-dev-qa-db-fra.com

Comment utiliser les expressions rationnelles JavaScript sur plusieurs lignes?

var ss= "<pre>aaaa\nbbb\nccc</pre>ddd";
var arr= ss.match( /<pre.*?<\/pre>/gm );
alert(arr);     // null

J'aimerais que le bloc PRE soit capté, même s'il s'étend sur des caractères de nouvelle ligne. Je pensais que le drapeau 'm' le faisait. Ne fait pas.

Trouvé la réponse ici avant de poster. Depuis que je pensais connaître JavaScript (lire trois livres, travailler) et qu’il n’y avait pas de solution existante chez SO, j’oserai quand même poster. jette des pierres ici

La solution est donc:

var ss= "<pre>aaaa\nbbb\nccc</pre>ddd";
var arr= ss.match( /<pre[\s\S]*?<\/pre>/gm );
alert(arr);     // <pre>...</pre> :)

Quelqu'un at-il un moyen moins crypté?

Edit: this est un doublon, mais comme il est plus difficile à trouver que le mien, je ne l'enlève pas.

Il propose [^] comme "point multiligne". Ce que je ne comprends toujours pas, c'est pourquoi [.\n] ne fonctionne pas. Devinez que c'est l'une des parties tristes de JavaScript ..

223
akauppi

[.\n] ne fonctionne pas car . n'a pas de signification particulière à l'intérieur de [], cela signifie simplement un . littéral. (.|\n) serait un moyen de spécifier "n'importe quel caractère, y compris une nouvelle ligne". Si vous souhaitez faire correspondre toutes les nouvelles lignes, vous devez également ajouter \r pour inclure les fins de ligne de style Windows et Mac OS classique: (.|[\r\n]).

Cela s'avère être un peu lourd et lent (voir La réponse de KrisWebDev pour plus de détails ), une meilleure approche serait donc de faire correspondre tous les caractères blancs et tous les caractères non blancs, avec [\s\S], ce qui correspond à tout. , et est plus rapide et plus simple.

En général, vous ne devriez pas essayer d'utiliser une expression rationnelle pour faire correspondre les balises HTML réelles. Voir, par exemple, cesquestions pour plus d’informations sur les raisons.

Essayez plutôt de rechercher dans le DOM la balise dont vous avez besoin (jQuery facilite cette opération, mais vous pouvez toujours utiliser document.getElementsByTagName("pre") avec le DOM standard), puis recherchez le contenu textuel de ces résultats avec une expression rationnelle si vous Contenu.

197
Brian Campbell

NE PAS utiliser (.|[\r\n]) au lieu de . pour la correspondance multiligne.

DO utilisez [\s\S] au lieu de . pour la correspondance multiligne

Aussi, évitez la gourmandise si elle n’est pas nécessaire en utilisant le quantificateur *? ou +? au lieu de * ou + Cela peut avoir un impact énorme sur les performances.

Voir la référence que j'ai faite: http://jsperf.com/javascript-multiline-regexp-workarounds

Using [^]: fastest
Using [\s\S]: 0.83% slower
Using (.|\r|\n): 96% slower
Using (.|[\r\n]): 96% slower

NB: Vous pouvez également utiliser [^] mais il est déconseillé dans le commentaire ci-dessous.

292
KrisWebDev

[.\n] ne fonctionne pas, car point dans [] (selon la définition regex; pas uniquement en javascript) signifie le caractère point. Vous pouvez utiliser (.|\n) (ou (.|[\n\r])) à la place.

12
Y. Shoham

Vous ne spécifiez pas votre environnement et votre version de Javascript (ECMAscript), et je me rends compte que ce post date de 2009, mais pour que tout soit complet, avec la publication de ECMA2018, nous pouvons maintenant utiliser le drapeau s pour que . corresponde à «\ n», voir https://stackoverflow.com/a/36006948/141801

Ainsi:

let s = 'I am a string\nover several\nlines.';
console.log('String: "' + s + '".');

let r = /string.*several.*lines/s; // Note 's' modifier
console.log('Match? ' + r.test(s); // 'test' returns true

Ceci est un ajout récent et ne fonctionnera pas dans beaucoup d’environnements actuels, par exemple, Node v8.7.0 ne semble pas le reconnaître, mais il fonctionne en Chromium, et je l’utilise dans un test TypeScript que j’écris. deviendra plus grand public au fil du temps.

10
Neek

Je l'ai testé (Chrome) et il fonctionne pour moi ([^] et [^\0]) en modifiant le point (.) soit par [^\0], soit par [^], car ce dernier ne correspond pas à la ligne (voir ici: http://www.regular-expressions.info/dot.html).

var ss= "<pre>aaaa\nbbb\nccc</pre>ddd";
var arr= ss.match( /<pre[^\0]*?<\/pre>/gm );
alert(arr);     //Working

6
KhunRan

En plus des exemples ci-dessus, il s'agit d'une alternative.

^[\\w\\s]*$

\w est pour les mots et \s est pour les espaces blancs

0
itz-azhar