正则表达式在Javascript中获取两个字符串之间的字符串

我发现了非常相似的帖子,但我不能完全得到我的正则表达式在这里。

我试图写一个正则表达式,它返回一个字符串,这是两个其他字符串之间。例如:我想获取位于字符串“cow”和“milk”之间的字符串。

我的奶牛总是产奶

将返回

“总是”

以下是我到目前为止拼凑的表达方式:

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

然而,这将返回字符串“cow always gives”。

592106 次浏览

前瞻((?=部分)不消耗任何输入。它是零宽度断言(边界检查和向后查找也是如此)。

这里需要一个常规匹配,以使用cow部分。为了捕获中间的部分,你使用一个捕获组(只需将你想捕获的部分放在括号内):

cow(.*)milk

根本不需要观察头。

  • 你需要捕获.*
  • 你可以(但不必)使.*非贪婪
  • 真的没有必要向前看。

    > /cow(.*?)milk/i.exec('My cow always gives milk');
    ["cow always gives milk", " always gives "]
    

下面是一个正则表达式,它将抓取奶牛和牛奶之间的内容(没有前导/尾随空格):

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

一个例子:http://jsfiddle.net/entropo/tkP74/

只需使用下面的正则表达式:

(?<=My cow\s).*?(?=\smilk)

正则表达式在JavaScript中获取两个字符串之间的字符串

在绝大多数情况下工作的最完整的解决方案是使用捕获组惰性点匹配模式。然而,JavaScript正则表达式中的点.不匹配换行字符,因此,在100%的情况下可以使用[^][\s\S]/[\d\D]/[\w\W]结构。

ECMAScript 2018和更新的兼容解决方案

在支持ECMAScript 2018的JavaScript环境中,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,在cow之后有任何1/0或更多的空格,然后匹配并消耗尽可能少的任何0+字符(=添加到匹配值中),然后检查milk(在此子字符串之前有任何1/0或更多的空格)。

场景一:单行输入

所有JavaScript环境都支持以下所有场景。参见答案底部的用法示例

cow (.*?) milk

首先找到cow,然后是一个空格,然后是除换行字符以外的任何0+字符(因为*?是一个惰性量词,所以尽可能少)被捕获到第1组,然后必须跟随一个带有milk的空格(这些也被匹配,还有消耗)。

场景2:多行输入

cow ([\s\S]*?) milk

这里,首先匹配cow和一个空格,然后匹配尽可能少的0+字符并捕获到第1组,然后匹配具有milk的空格。

场景3:重叠匹配

如果你有一个像>>>15 text>>>67 text2>>>这样的字符串,你需要在>>>+number+whitespace>>>之间得到两个匹配,你不能使用/>>>\d+\s(.*?)>>>/g,因为这只会找到一个匹配,因为在找到第一个匹配时,67之前的>>>已经是消耗了。你可以使用>>>0来检查文本是否存在,而不是真正的“gobbling”。它(即附加到匹配项):

/>>>\d+\s(.*?)(?=>>>)/g

请参阅在线正则表达式演示生成text1text2作为找到的第1组内容。

也可参见如何获得一个字符串的所有可能的重叠匹配

性能考虑

如果给出很长的输入,regex模式中的惰性点匹配模式(.*?)可能会降低脚本执行速度。在许多情况下,< em > < / em > unroll-the-loop技术在更大程度上有帮助。试图从"Their\ncow\ngives\nmore\nmilk"中抓取cowmilk之间的所有行,我们看到我们只需要匹配所有不以milk开头的行,因此,我们可以使用:

/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]));

我能够得到我需要使用Martinho Fernandes的解决方案如下。代码是:

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

我选择的答案不适合我……嗯……

只要在cow后面和/或milk前面添加空格,就可以从“always gives”中删除空格

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

enter image description here

方法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]

我发现正则表达式是乏味和耗时的语法。因为你已经在使用javascript,所以不使用regex更容易做到以下几点:

const text = 'My cow always gives milk'
const start = `cow`;
const end = `milk`;
const middleText = text.split(start)[1].split(end)[0]
console.log(middleText) // prints "always gives"

任务

在两个字符串之间提取子字符串(不包括这两个字符串)

解决方案

let allText = "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum";
let textBefore = "five centuries,";
let textAfter = "electronic typesetting";
var regExp = new RegExp(`(?<=${textBefore}\\s)(.+?)(?=\\s+${textAfter})`, "g");
var results = regExp.exec(allText);
if (results && results.length > 1) {
console.log(results[0]);
}

如果数据在多行上,那么您可能必须使用以下方法,

/My cow ([\s\S]*)milk/gm


My cow always gives
milk

Regex 101 example

你可以使用解构来只关注你感兴趣的部分。

所以你可以这样做:

let str = "My cow always gives milk";


let [, result] = str.match(/\bcow\s+(.*?)\s+milk\b/) || [];


console.log(result);

通过这种方式,您可以忽略第一部分(完整的匹配),而只获得捕获组的匹配。如果你根本不确定是否会有匹配,添加|| []可能会很有趣。在这种情况下,match将返回不能被解构的null,因此在这种情况下,我们将返回[],然后result将是null

额外的\b确保周围的单词"cow"和“;milk"是完全独立的单词(例如:not "milky")还需要\s+来避免匹配包含一些外间距。

可以使用match()方法提取两个字符串之间的子字符串。试试下面的代码:

var str = "My cow always gives milk";
var subStr = str.match("cow(.*)milk");
console.log(subStr[1]);

输出:

总是给

在这里查看完整的示例:如何在两个字符串之间找到子字符串