Многострочный флаг регулярных выражений Javascript не работает
Я написал регулярное выражение для извлечения строки из HTML, но кажется, что многострочный флаг не работает.
это мой шаблон, и я хочу получить текст в теге h1.
var pattern= /<div class="box-content-5">.*<h1>([^<]+?)<\/h1>/mi
m = html.search(pattern);
return m[1];
Я создал строку, чтобы проверить это. Когда строка содержит "\ n", результат всегда будет нулевым. Если я удаляю все "\ n", это дает мне правильный результат, независимо от того, с /m флагом или без.
что не так с моим регулярным выражением?
4 ответа
Вы ищете /.../s
модификатор, также известный как модификатор dotall. Это заставляет точку .
также соответствовать символам новой строки, чего он не делает по умолчанию.
Плохая новость заключается в том, что он не существует в JavaScript (он существует на ES2018, см. Ниже). Хорошей новостью является то, что вы можете обойти это, используя класс персонажа (например, \s
) и его отрицание (\S
) вместе вот так:
[\s\S]
Так что в вашем случае регулярное выражение станет:
/<div class="box-content-5">[\s\S]*<h1>([^<]+?)<\/h1>/i
Начиная с ES2018, JavaScript поддерживает s
(dotAll), поэтому в современной среде ваше регулярное выражение может быть таким, как вы его написали, но с s
флаг в конце (а не m
; m
меняет как ^
а также $
работать, а не .
):
/<div class="box-content-5">.*<h1>([^<]+?)<\/h1>/is
Вы хотите s
модификатор (dotall), которого, очевидно, нет в Javascript - вы можете заменить .
с [\s\S], как предложено @molf. m
Модификатор (multiline) создает строки соответствия ^ и $, а не всю строку.
[\s\S]
у меня не работало в nodejs 6.11.3. Основываясь на документации RegExp, он говорит, чтобы использовать [^]
который работает для меня.
(Точка, десятичная точка) соответствует любому отдельному символу, кроме ограничителей строки: \n, \r, \u2028 или \u2029.
Внутри набора символов точка теряет свое особое значение и соответствует буквальной точке.
Обратите внимание, что многострочный флаг m не меняет поведение точек. Таким образом, чтобы сопоставить шаблон с несколькими строками, можно использовать набор символов [^] (если, конечно, вы не имеете в виду старую версию IE), он будет соответствовать любому символу, включая символы новой строки.
Например:
/This is on line 1[^]*?This is on line 3/m
где *? не жадный захват 0 или более вхождений [^].
Модификатор dotall фактически превратил его в JavaScript в июне 2018 года, то есть ECMAScript 2018.
https://github.com/tc39/proposal-regexp-dotall-flag
const re = /foo.bar/s; // Or, `const re = new RegExp('foo.bar', 's');`.
re.test('foo\nbar');
// → true
re.dotAll
// → true
re.flags
// → 's'
Фактически, модификатор dotall, который заставляет точку соответствовать символам новой строки, теперь находится на стадии 4 процесса TC39, что означает, что он готов к реализации.
Вы можете посмотреть на предложение здесь, это просто дополнение s
флаг.
Использование в значительной степени похоже на это:
/foo.bar/s.test('foo\nbar');
// → true
и API высокого уровня:
const re = /foo.bar/s; // Or, `const re = new RegExp('foo.bar', 's');`.
re.test('foo\nbar');
// → true
re.dotAll
// → true
re.flags
// → 's'
Как написано в документах, оно реализовано в V8 из chrome 62 и в: Создайте будущее Интернета с помощью современного JavaScript (Google I/O '18), говорят, что оно уже реализовано в Chrome, Opera, Safari и NodeJS. Babel также может использовать его для браузеров, которые его не поддерживают.
Эту функцию также можно увидеть в черновиках документов TC39.
Мое предложение состоит в том, что лучше разделить многострочную строку с помощью "\n" и объединить разбиения исходной строки и превратить ее в одну строку, которой легко манипулировать.
<textarea class="form-control" name="Body" rows="12" data-rule="required"
title='@("Your feedback ".Label())'
placeholder='@("Your Feedback here!".Label())' data-val-required='@("Feedback is required".Label())'
pattern="^[0-9a-zA-Z ,;/?.\s_-]{3,600}$" data-val="true" required></textarea>
$( document ).ready( function() {
var errorMessage = "Please match the requested format.";
var firstVisit = false;
$( this ).find( "textarea" ).on( "input change propertychange", function() {
var pattern = $(this).attr( "pattern" );
var element = $( this );
if(typeof pattern !== typeof undefined && pattern !== false)
{
var ptr = pattern.replace(/^\^|\$$/g, '');
var patternRegex = new RegExp('^' + pattern.replace(/^\^|\$$/g, '') + '$', 'gm');
var ks = "";
$.each($( this ).val().split("\n"), function( index, value ){
console.log(index + "-" + value);
ks += " " + value;
});
//console.log(ks);
hasError = !ks.match( patternRegex );
//debugger;
if ( typeof this.setCustomValidity === "function")
{
this.setCustomValidity( hasError ? errorMessage : "" );
}
else
{
$( this ).toggleClass( "invalid", !!hasError );
$( this ).toggleClass( "valid", !hasError );
if ( hasError )
{
$( this ).attr( "title", errorMessage );
}
else
{
$( this ).removeAttr( "title" );
}
}
}
});
});