如何使正则表达式变为非贪婪?


226

我正在使用jQuery。我有一个带有特殊字符块(开头和结尾)的字符串。我想从特殊字符块中获取文本。我使用正则表达式对象进行字符串内查找。但是当有两个或两个以上特殊字符时,如何告诉jQuery查找多个结果?

我的HTML:

<div id="container">
    <div id="textcontainer">
     Cuc chiến pháp lý gia [|cơ thử|nghim|] th trường [|test2|đây là test ln 2|] chng khoán [|Mỹ|day la nuoc my|] và ngân hàng đầu tư quyn lc nht Ph Wall mi ch bt đầu.
    </div>
</div>

和我的JavaScript代码:

$(document).ready(function() {
  var takedata = $("#textcontainer").text();
  var test = 'abcd adddb';
  var filterdata = takedata.match(/(\[.+\])/);

  alert(filterdata); 

  //end write js 
});

我的结果是:[|cơthử|nghiệm|]thịtrường[| test2 |đâylàtestlần2 |]chứngkhoán[|Mỹ| day la nuoc my |]。但是,这不是我想要的结果:(。如何获取时间1的[文本]和时间2的[演示]?


在互联网上搜索信息后,我才完成^^。我编写如下代码:

var filterdata = takedata.match(/(\[.*?\])/g);
  • 我的结果是:[|cơthử|nghiệm|],[| test2 |đâylàtestlần2 |] 这是对的!但是我不太明白 你能回答我为什么吗?

Answers:


491

非贪婪的正则表达式修饰符就像它们的贪婪对应部分,但?紧随其后:

*  - zero or more
*? - zero or more (non-greedy)
+  - one or more
+? - one or more (non-greedy)
?  - zero or one
?? - zero or one (non-greedy)

29
可能有用的是?,它本身的意思是“一或零”(但是很贪心!)。例如,'bb'.replace(/b?/, 'a') //'ab'以及'bb'.replace(/c?/, 'a') //'abb'
Hashbrown,

1
c那里什么都不匹配
穆罕默德·乌默尔

1
@MuhammadUmer我认为他的建议是因为c将不匹配,但是您有?,即0 or 1,那么它将匹配0 number of c characters,因此将其替换。我不知道它是如何工作,但因为这并不在任何正则表达式引擎编译我已经试过😢
Noctis

35

没错,贪婪是一个问题:

--A--Z--A--Z--
  ^^^^^^^^^^
     A.*Z

如果您想两者都匹配A--Z,则必须使用A.*?Z(这?使*“不情愿”或懒惰)。

不过,有时候有更好的方法可以做到这一点,例如

A[^Z]*+Z

这使用否定的字符类和所有格量词来减少回溯,并且可能更有效。

在您的情况下,正则表达式为:

/(\[[^\]]++\])/

不幸的是, Javascript正则表达式不支持所有格量​​词,因此您只需要处理以下内容:

/(\[[^\]]+\])/

也可以看看


快速总结

*   Zero or more, greedy
*?  Zero or more, reluctant
*+  Zero or more, possessive

+   One or more, greedy
+?  One or more, reluctant
++  One or more, possessive

?   Zero or one, greedy
??  Zero or one, reluctant
?+  Zero or one, possessive

注意,勉强量词和所有格量词也适用于有限重复{n,m}构造。

Java中的示例:

System.out.println("aAoZbAoZc".replaceAll("A.*Z", "!"));  // prints "a!c"
System.out.println("aAoZbAoZc".replaceAll("A.*?Z", "!")); // prints "a!b!c"

System.out.println("xxxxxx".replaceAll("x{3,5}", "Y"));  // prints "Yx"
System.out.println("xxxxxx".replaceAll("x{3,5}?", "Y")); // prints "YY"

我将您的正则表达式复制到我的工作中,结果是:无效的量词+ \])[此错误中断] var filterdata = takedata.match(/(\([[[^ \]] ++ \])/)/); \ n(萤火虫+ Firefox)有问题吗?
Rueta 2010年

@Rueta:显然Javascript风格不支持所有格。我已经修改了答案以反映这一事实。您只能使用一个+而不是两个。
多基因润滑剂

1
尽管可以使用原子组来代替所有格修饰符,但是JavaScript也不支持原子组。但还有第三种选择,请参阅本:instanceof.me/post/52245507631/... -you can emulate atomic grouping with LookAhead. (?>a) becomes (?=(a))\1
罗兰Pihlakas

2
这是JavaScript问题的Java答案,而Java!= JavaScript。读者,请注意。
Roshambo

3

我相信会是这样

takedata.match(/(\[.+\])/g);

g末意味着全球性的,所以它不会在第一场比赛停止。


是的,您对/ g是正确的。我刚刚用您的答案/ g ^^完成了我的工作。但是当我将规则设为/(\[.+\])/g时,我的结果是:[|cơthử|nghiệm|]thịtrường[| test2 |đâylàtestlần2 |]chứngkhoán[|Mỹ| day la nuoc my |] :(
Rueta 2010年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.