Регулярное выражение для получения строки между двумя строками в JavaScript
Наиболее полное решение, которое будет работать в подавляющем большинстве случаев, - это использование группы захвата с ленивым шаблоном сопоставления точек . Тем не менее, точка .в регулярном выражении JavaScript не соответствует символам разрыва строки, поэтому в 100% случаев будет работать конструкция a [^]или [\s\S]/ [\d\D]/ [\w\W].
ECMAScript 2018 и более новые совместимые решения
В средах JavaScript, поддерживающих ECMAScript 2018 , sмодификатор позволяет .сопоставлять любой символ, включая символы разрыва строки, а механизм регулярных выражений поддерживает вид сзади переменной длины. Таким образом, вы можете использовать регулярные выражения, такие как
var result = s.match(/(?<=cow\s+).*?(?=\s+milk)/gs); // Returns multiple matches if any
// Or
var result = s.match(/(?<=cow\s*).*?(?=\s*milk)/gs); // Same but whitespaces are optional
В обоих случаях текущая позиция проверяется cowс любыми 1/0 или более пробелами после cow, затем любые 0+ символов, как можно меньше, сопоставляются и потребляются (= добавляются к значению соответствия), а затем milkпроверяются на (с любым 1/0 или больше пробелов перед этой подстрокой).
Сценарий 1: однострочный ввод
Этот и все другие сценарии ниже поддерживаются всеми средами JavaScript. Смотрите примеры использования в нижней части ответа.
cow (.*?) milk
cowсначала определяется, затем пробел, затем любые 0+ символов, кроме символов разрыва строки, как можно меньше, чем *?ленивый квантификатор, включаются в группу 1, а затем следует пробел с milk(и те, которые сопоставляются и потребляются , тоже ).
Сценарий 2: многострочный ввод
cow ([\s\S]*?) milk
Здесь cowи пробел сначала сопоставляется, затем любые 0+ символов, как можно меньше, сопоставляются и включаются в Группу 1, а затем пробел с milkсопоставляются.
Сценарий 3: перекрывающиеся совпадения
Если у вас есть строка типа, >>>15 text>>>67 text2>>>и вам нужно получить 2 совпадения между >>>+ number+ whitespaceи >>>, вы не можете использовать, так />>>\d+\s(.*?)>>>/gкак вы найдете только 1 совпадение из-за того факта, что >>>предыдущий 67уже используется при поиске первого совпадения. Вы можете использовать позитивный взгляд, чтобы проверить наличие текста без фактического «сожрания» его (т. Е. Добавления к совпадению):
/>>>\d+\s(.*?)(?=>>>)/g
Смотрите онлайн регулярное выражение демо приносит text1и text2в группе найдено 1 содержание.
Также смотрите Как получить все возможные совпадения для строки .
Вопросы производительности
Lazy dot match pattern ( .*?) внутри шаблонов регулярных выражений может замедлить выполнение скрипта, если задан очень длинный ввод. Во многих случаях техника «развернуть петлю» помогает в большей степени. Пытаясь получить все между cowи milkиз "Their\ncow\ngives\nmore\nmilk", мы видим, что нам просто нужно сопоставить все строки, которые не начинаются с milk, таким образом, вместо того, cow\n([\s\S]*?)\nmilkчтобы использовать:
/cow\n(.*(?:\n(?!milk$).*)*)\nmilk/gm
Посмотрите демонстрацию regex (если возможно \r\n, используйте /cow\r?\n(.*(?:\r?\n(?!milk$).*)*)\r?\nmilk/gm). С этой небольшой тестовой строкой прирост производительности незначителен, но при очень большом тексте вы почувствуете разницу (особенно если строки длинные, а разрывы строк не очень многочисленны).
Пример использования регулярных выражений в JavaScript:
//Single/First match expected: use no global modifier and access match[1]
console.log("My cow always gives milk".match(/cow (.*?) milk/)[1]);
// Multiple matches: get multiple matches with a global modifier and
// trim the results if length of leading/trailing delimiters is known
var s = "My cow always gives milk, thier cow also gives milk";
console.log(s.match(/cow (.*?) milk/g).map(function(x) {return x.substr(4,x.length-9);}));
//or use RegExp#exec inside a loop to collect all the Group 1 contents
var result = [], m, rx = /cow (.*?) milk/g;
while ((m=rx.exec(s)) !== null) {
result.push(m[1]);
}
console.log(result);
Используя современный String#matchAllметод
const s = "My cow always gives milk, thier cow also gives milk";
const matches = s.matchAll(/cow (.*?) milk/g);
console.log(Array.from(matches, x => x[1]));