我发现了非常相似的帖子,但是我在这里无法完全得到正则表达式。
我正在尝试编写一个正则表达式,该表达式返回一个位于其他两个字符串之间的字符串。例如:我想获取字符串“ cow”和“ milk”之间的字符串。
我的牛总是喂牛奶
会回来
“总是给”
到目前为止,这是我拼凑的表达方式:
(?=cow).*(?=milk)
但是,这将返回字符串“牛总是给”。
我发现了非常相似的帖子,但是我在这里无法完全得到正则表达式。
我正在尝试编写一个正则表达式,该表达式返回一个位于其他两个字符串之间的字符串。例如:我想获取字符串“ cow”和“ milk”之间的字符串。
我的牛总是喂牛奶
会回来
“总是给”
到目前为止,这是我拼凑的表达方式:
(?=cow).*(?=milk)
但是,这将返回字符串“牛总是给”。
Answers:
前瞻(该(?=
部分)不消耗任何输入。这是一个零宽度的断言(边界检查和回溯也是如此)。
您要在此处进行常规匹配以消耗该cow
部分。要捕获之间的部分,可以使用捕获组(只需将要捕获的模式部分放在括号内):
cow(.*)milk
完全不需要前瞻。
matched[1]
的匹配文本,而不是使用提取整个匹配文本matched[0]
。
([\s\S]*?)
而不是(.*?)
。
正则表达式以获取JavaScript中两个字符串之间的字符串
在绝大多数情况下,最完整的解决方案是使用具有惰性点匹配模式的捕获组。然而,一个点在JavaScript中的正则表达式不匹配换行符,所以,你会在100%的情况下工作是一种或/ / 构造。.
[^]
[\s\S]
[\d\D]
[\w\W]
在支持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或更多空格的当前位置cow
,然后匹配并消耗尽可能少的任何0+个字符(=添加到匹配值中),然后milk
检查(是否有任何此子字符串前的1/0或多个空格)。
所有JavaScript环境都支持以下这种情况以及所有其他情况。请参阅答案底部的用法示例。
cow (.*?) milk
cow
首先找到一个空格,然后将除换行符以外的所有0+个字符(尽可能少的作为*?
惰性量)捕获到组1中,然后milk
必须跟随一个空格(并且匹配并消耗了这些空格),也)。
cow ([\s\S]*?) milk
在这里,cow
先匹配一个空格,然后匹配尽可能少的任何0+个字符并将其捕获到组1中,然后使用milk
匹配。
如果您有一个类似这样的字符串,>>>15 text>>>67 text2>>>
并且您需要在>>>
+ number
+ whitespace
和之间获得2个匹配项>>>
,则您将无法使用它,/>>>\d+\s(.*?)>>>/g
因为只能找到1个匹配项,因为查找第一个匹配项>>>
之前67
已经消耗了before 的事实。您可以使用正向前瞻来检查文本是否存在,而无需实际“吞噬”文本(即追加到匹配项中):
/>>>\d+\s(.*?)(?=>>>)/g
参见在线正则表达式演示 yield 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);
使用现代
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]));
这是一个正则表达式,它将捕获牛奶和牛奶之间的内容(没有前导/尾随空间):
srctext = "My cow always gives milk.";
var re = /(.*cow\s+)(.*)(\s+milk.*)/;
var newtext = srctext.replace(re, "$2");
?<=
Javascript不支持“向后看” 。
使用下面的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
只需使用以下正则表达式:
(?<=My cow\s).*?(?=\smilk)
?<=
Javascript不支持“向后看” 。将会是这样做的方式。
考虑到语法,我发现正则表达式既繁琐又耗时。由于您已经在使用javascript,因此无需使用正则表达式即可更轻松地执行以下操作:
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]);
}