javascript regex - 寻找替代方案?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7376238/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
javascript regex - look behind alternative?
提问by daniel
Here is a regex that works fine in most regex implementations:
这是一个在大多数正则表达式实现中都能正常工作的正则表达式:
(?<!filename)\.js$
This matches .js for a string which ends with .js except for filename.js
这与 .js 匹配以 .js 结尾的字符串,除了 filename.js
Javascript doesn't have regex lookbehind. Is anyone able put together an alternative regex which achieve the same result and works in javascript?
Javascript 没有正则表达式后视。有没有人能够组合一个替代的正则表达式来实现相同的结果并在 javascript 中工作?
Here are some thoughts, but needs helper functions. I was hoping to achieve it just with a regex: http://blog.stevenlevithan.com/archives/mimic-lookbehind-javascript
这里有一些想法,但需要辅助函数。我希望只用一个正则表达式来实现它:http: //blog.stevenlevithan.com/archives/mimic-lookbehind-javascript
采纳答案by Benjamin Udink ten Cate
^(?!filename).+\.js
works for me
^(?!filename).+\.js
为我工作
tested against:
测试针对:
- test.js match
- blabla.js match
- filename.js no match
- test.js 匹配
- blabla.js 匹配
- 文件名.js 不匹配
A proper explanation for this regex can be found at Regular expression to match string not containing a word?
可以在正则表达式匹配不包含单词的字符串中找到此正则表达式的正确解释?
Look ahead is available since version 1.5 of javascriptand is supported by all major browsers
自javascript 1.5 版起就可以使用预读功能,并且所有主要浏览器都支持
Updatedto match filename2.js and 2filename.js but not filename.js
更新以匹配 filename2.js 和 2filename.js 但不匹配 filename.js
(^(?!filename\.js$).).+\.js
(^(?!filename\.js$).).+\.js
回答by Tim Pietzcker
EDIT: From ECMAScript 2018 onwards, lookbehind assertions (even unbounded) are supported natively.
编辑:从 ECMAScript 2018 开始,本机支持后视断言(甚至无界)。
In previous versions, you can do this:
在以前的版本中,您可以这样做:
^(?:(?!filename\.js$).)*\.js$
This does explicitly what the lookbehind expression is doing implicitly: check each character of the string if the lookbehind expression plus the regex after it will not match, and only then allow that character to match.
这明确地执行了lookbehind 表达式隐式执行的操作:如果lookbehind 表达式加上后面的正则表达式不匹配,则检查字符串的每个字符,然后才允许该字符匹配。
^ # Start of string
(?: # Try to match the following:
(?! # First assert that we can't match the following:
filename\.js # filename.js
$ # and end-of-string
) # End of negative lookahead
. # Match any character
)* # Repeat as needed
\.js # Match .js
$ # End of string
Another edit:
另一个编辑:
It pains me to say (especially since this answer has been upvoted so much) that there is a far easier way to accomplish this goal. There is no need to check the lookahead at every character:
我很痛苦地说(特别是因为这个答案已经得到了如此多的支持)有一种更简单的方法来实现这个目标。无需检查每个字符的前瞻:
^(?!.*filename\.js$).*\.js$
works just as well:
也能正常工作:
^ # Start of string
(?! # Assert that we can't match the following:
.* # any string,
filename\.js # followed by filename.js
$ # and end-of-string
) # End of negative lookahead
.* # Match any string
\.js # Match .js
$ # End of string
回答by Kamil Szot
Let's suppose you want to find all int
not preceded by unsigned
:
假设您想查找所有int
不以 开头的内容unsigned
:
With support for negative look-behind:
支持负向后视:
(?<!unsigned )int
Without support for negative look-behind:
不支持负向后视:
((?!unsigned ).{9}|^.{0,8})int
Basically idea is to grab n preceding characters and exclude match with negative look-ahead, but also match the cases where there's no preceeding n characters. (where n is length of look-behind).
基本上的想法是抓取 n 个前面的字符并排除带有否定前瞻的匹配,但也匹配没有前面 n 个字符的情况。(其中 n 是后视的长度)。
So the regex in question:
所以有问题的正则表达式:
(?<!filename)\.js$
would translate to:
会翻译成:
((?!filename).{8}|^.{0,7})\.js$
You might need to play with capturing groups to find exact spot of the string that interests you or you want't to replace specific part with something else.
您可能需要使用捕获组来找到您感兴趣的字符串的确切位置,或者您不想用其他内容替换特定部分。
回答by Albert Friend
If you can look ahead but back, you could reverse the string first and then do a lookahead. Some more work will need to be done, of course.
如果您可以向前看但可以向后看,您可以先反转字符串,然后再向前看。当然,还需要做一些工作。
回答by weibeld
This is an equivalent solution to Tim Pietzcker's answer(see also comments of same answer):
这是Tim Pietzcker 答案的等效解决方案(另请参阅相同答案的评论):
^(?!.*filename\.js$).*\.js$
It means, match *.js
except *filename.js
.
这意味着,匹配*.js
除了*filename.js
。
To get to this solution, you can check which patterns the negative lookbehind excludes, and then exclude exactly these patterns with a negative lookahead.
要获得此解决方案,您可以检查负向后视排除了哪些模式,然后使用负向后视准确排除这些模式。
回答by Piotr Berebecki
Below is a positive lookbehind JavaScript alternative showing how to capture the last name of people with 'Michael' as their first name.
下面是一个正面的 Lookbehind JavaScript 替代方案,展示了如何捕获以“Michael”作为名字的人的姓氏。
1) Given this text:
1) 鉴于此文本:
const exampleText = "Michael, how are you? - Cool, how is John Williamns and Michael Jordan? I don't know but Michael Johnson is fine. Michael do you still score points with LeBron James, Michael Green Miller and Michael Wood?";
get an array of last names of people named Michael.
The result should be: ["Jordan","Johnson","Green","Wood"]
获取名为 Michael 的人的姓氏数组。结果应该是:["Jordan","Johnson","Green","Wood"]
2) Solution:
2) 解决方法:
function getMichaelLastName2(text) {
return text
.match(/(?:Michael )([A-Z][a-z]+)/g)
.map(person => person.slice(person.indexOf(' ')+1));
}
// or even
.map(person => person.slice(8)); // since we know the length of "Michael "
3) Check solution
3) 检查解决方案
console.log(JSON.stringify( getMichaelLastName(exampleText) ));
// ["Jordan","Johnson","Green","Wood"]
Demo here: http://codepen.io/PiotrBerebecki/pen/GjwRoo
演示在这里:http: //codepen.io/PiotrBerebecki/pen/GjwRoo
You can also try it out by running the snippet below.
您也可以通过运行下面的代码段来尝试一下。
const inputText = "Michael, how are you? - Cool, how is John Williamns and Michael Jordan? I don't know but Michael Johnson is fine. Michael do you still score points with LeBron James, Michael Green Miller and Michael Wood?";
function getMichaelLastName(text) {
return text
.match(/(?:Michael )([A-Z][a-z]+)/g)
.map(person => person.slice(8));
}
console.log(JSON.stringify( getMichaelLastName(inputText) ));