Как использовать регулярное выражение JavaScript для нескольких строк?

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

Я бы хотел, чтобы блок PRE был поднят, хотя он охватывает символы новой строки. Я думал, что флаг "m" делает это. Не делает.

Найден ответ здесь перед публикацией. SInce Я думал, что знаю JavaScript (читал три книги, работал часов), и в SO не было никакого решения, я все равно осмелюсь публиковать. бросать камни здесь

Итак, решение:

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

Есть ли у кого-нибудь менее загадочный способ?

Изменить: this является дубликатом, но, поскольку его сложнее найти, чем у меня, я не удаляю.

Он предлагает [^] как "многострочную точку". Я все еще не понимаю, почему [.\n] не работает. Угадайте, что это одна из грустных частей JavaScript.

Ответ 1

[.\n] не работает, потому что . не имеет особого значения внутри [], это просто означает литерал .. (.|\n) - это способ указать "любой символ, включая новую строку". Если вы хотите совместить все новые строки, вам нужно будет добавить \r, чтобы включить окончание строк стиля Windows и классического Mac OS: (.|[\r\n]).

Это оказывается несколько громоздким, а также медленным (см. ответ KrisWebDev для деталей), поэтому лучшим подходом было бы сопоставление всех символов пробелов и все символы без пробелов, с [\s\S], которые будут соответствовать всем, и быстрее и проще.

В общем, вы не должны пытаться использовать регулярное выражение для соответствия фактическим тегам HTML. См., Например, эти questions для получения дополнительной информации о том, почему.

Вместо этого попробуйте выполнить поиск DOM в нужном вам теге (использование jQuery делает это проще, но вы всегда можете сделать document.getElementsByTagName("pre") со стандартным DOM), а затем искать текстовое содержимое этих результатов с помощью регулярного выражения, если вы необходимо сопоставить с содержимым.

Ответ 2

НЕ используйте (.|[\r\n]) вместо . для многострочного сопоставления.

Используйте [\s\S] вместо . для многострочного соответствия

Также избегайте жадности, если это не нужно, используя квантор *? или +? вместо * или +. Это может иметь огромное влияние на производительность.

См. контрольный показатель, который я сделал: 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

Примечание. Вы также можете использовать [^], но в приведенном ниже комментариях он устарел.

Ответ 3

[.\n] не работает, потому что точка в [] (по определению regex, а не только по javascript) означает dot-character. Вместо этого вы можете использовать (.|\n) (или (.|[\n\r])).

Ответ 4

Я тестировал его (Chrome), и он работает для меня (как [^] и [^\0]), меняя точку (.) на [^\0] или [^], потому что точка не (см. здесь 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