Регулярное выражение для получения строки между двумя строками в Javascript - PullRequest
128 голосов
/ 13 апреля 2011

Я нашел очень похожие сообщения, но я не могу получить мое регулярное выражение прямо здесь.

Я пытаюсь написать регулярное выражение, которое возвращает строку, которая находится между двумя другими строками.Например: я хочу получить строку, которая находится между строками "корова" и "молоко".

Моя корова всегда дает молоко

вернется

"всегда дает"

Вот выражение, которое я сложил до сих пор:

(?=cow).*(?=milk)

Однако, это возвращает строку "корова всегда дает".

Ответы [ 8 ]

151 голосов
/ 13 апреля 2011

Взгляд (который (?= часть) не потребляет никакого ввода.Это утверждение нулевой ширины (как и проверки границ и вид сзади).

Вы хотите здесь регулярное совпадение, чтобы использовать часть cow.Чтобы захватить промежуточную часть, вы используете группу захвата (просто поместите часть шаблона, которую вы хотите захватить, в круглые скобки):

cow(.*)milk

Никаких предварительных просмотров вообще не требуется.

53 голосов
/ 24 ноября 2016

Регулярное выражение для получения строки между двумя строками в JavaScript

Наиболее полное решение, которое будет работать в подавляющем большинстве случаев, - это использование группы захвата с шаблоном сопоставления ленивых точек .Однако точка . в регулярном выражении JavaScript не соответствует символам разрыва строки, поэтому в 100% случаев будут работать конструкции [^] или [\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

См. online regex demo с результатом text1 и text2 в качестве найденного содержимого группы 1.

Также см. Как получить все возможные совпадения совпадений для строки .

Вопросы производительности

Шаблон сопоставления с отложенными точками (.*?) внутри шаблонов регулярных выражений может замедлить выполнение сценария, если задан очень длинный ввод.Во многих случаях метод развернутой петли помогает в большей степени.Пытаясь захватить все между 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);
49 голосов
/ 13 апреля 2011

Вот регулярное выражение, которое будет захватывать то, что находится между коровой и молоком (без пробела в начале / конце):

srctext = "My cow always gives milk.";
var re = /(.*cow\s+)(.*)(\s+milk.*)/;
var newtext = srctext.replace(re, "$2");

Пример: http://jsfiddle.net/entropo/tkP74/

15 голосов
/ 13 апреля 2011
  • Вам нужно захватить .*
  • Вы можете (но не обязаны) сделать .* нонгидай
  • Там действительно нет необходимостиВзгляд вперед.

    > /cow(.*?)milk/i.exec('My cow always gives milk');
    ["cow always gives milk", " always gives "]
    
6 голосов
/ 20 июля 2017

Я смог получить то, что мне было нужно, используя решение Мартино Фернандеса, приведенное ниже Код:

var test = "My cow always gives milk";

var testRE = test.match("cow(.*)milk");
alert(testRE[1]);

Вы заметите, что я оповещаю переменную testRE как массив. Это потому, что testRE по какой-то причине возвращается как массив. Выход из:

My cow always gives milk

Изменяется на:

always gives
5 голосов
/ 19 апреля 2018

Выбранный ответ не работал для меня ... хм ...

Просто добавьте пробел после коровы и / или перед молоком, чтобы урезать пробелы из "всегда дает"

/(?<=cow ).*(?= milk)/

enter image description here

3 голосов
/ 20 октября 2016

Просто используйте следующее регулярное выражение:

(?<=My cow\s).*?(?=\smilk)
0 голосов
/ 12 июня 2018

Метод match () ищет в строке совпадение и возвращает объект Array.

// Original string
var str = "My cow always gives milk";

// Using index [0] would return<br/>
// "**cow always gives milk**"
str.match(/cow(.*)milk/)**[0]**


// Using index **[1]** would return
// "**always gives**"
str.match(/cow(.*)milk/)[1]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...