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

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

我的奶牛总是产奶

将返回

“总是”

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

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

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


当前回答

您需要捕获。* 你可以(但不必)使。*非贪婪 真的没有必要向前看。 > /牛(. * ?)牛奶/我。exec(“我的奶牛总是产奶”); [“奶牛总是出奶”,“总是出奶”]

其他回答

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

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

示例:http://jsfiddle.net/entropo/tkP74/

我发现正则表达式是乏味和耗时的语法。因为你已经在使用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 str = "我的奶牛总是产奶"; 让[结果]= str.match (/ \ bcow \ s + (. * ?) \ \ b / s +牛奶)| | []; console.log(结果);

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

额外的\b确保了周围的单词“cow”和“milk”是真正独立的单词(例如,不是“milky”)。还需要使用\s+来避免匹配包含一些外间距。

? ?= part)不消耗任何输入。这是一个零宽度断言(边界检查和后视也是如此)。

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

cow(.*)milk

根本不需要观察头。

正则表达式在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后面有1/0或更多的空格,然后匹配并消耗尽可能少的任何0+字符(=添加到匹配值中),然后检查milk(在此子字符串之前有1/0或更多的空格)。

场景一:单行输入

所有JavaScript环境都支持这个场景和下面所有其他场景。请参阅答案底部的用法示例。

cow (.*?) milk

首先找到奶牛,然后是空格,然后是除换行字符以外的任何0+字符,尽可能少的*?是一个懒惰量词,被捕获到第1组,然后一个空格必须有牛奶(这些也被匹配和消耗)。

场景2:多行输入

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

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

场景3:重叠匹配

如果你有一个像>>>15 text>>>67 text2>>>,你需要在>>>+数字+空格和>>>之间得到2个匹配,你不能使用/>>>\d+\s(.*?)>>>/g,因为这只会找到1个匹配,因为在67之前的>>>已经在找到第一个匹配时被消耗掉了。你可以使用正向前瞻来检查文本是否存在,而不需要实际“吞掉”它(即附加到匹配项中):

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

请参阅在线regex演示,生成text1和text2作为找到的第1组内容。

另请参阅如何获取字符串的所有可能重叠匹配。

性能考虑

如果给出很长的输入,regex模式内的惰性点匹配模式(.*?)可能会降低脚本执行速度。在许多情况下,展开循环技术在很大程度上有帮助。试图从“Their\ncow\ngives\nmore\nmilk”中抓取奶牛和牛奶之间的所有内容,我们看到我们只需要匹配所有不以牛奶开头的行,因此,我们可以使用:

/cow\n(.*(?:\n(?!milk$).*)*)\nmilk/gm

看到regex演示(如果可以有\ r \ n,使用/牛\ r ? \ n (. * (?: \ r ? \ n(? !牛奶)美元。*)*)\ r ? \ nmilk /通用)。对于这个小的测试字符串,性能增益可以忽略不计,但是对于非常大的文本,您将感受到差异(特别是如果行很长并且换行符不是很多)。

Sample regex usage in 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 =“我的奶牛总是产奶,他们的奶牛也产奶”; const matches = s.matchAll(/cow (.*?) milk/g); console.log(Array.from(matches, x => x[1]));