是否需要使用非捕获组?

时间:2016-05-22 17:16:47

标签: regex

考虑一个例子,我在每一行都有一个文件名列表及其大小 -

file1.jpg   100
file-new.png    201
files.gif   102
exec.exe    200

如果我要替换所有这些(文件名和大小)jpg / gif / png ,我可以使用这个正则表达式 -

/.+(jpg|png|gif)\t[\d]+/g

或者(使用非捕获组) -

/.+(?:jpg|png|gif)\t[\d]+/g

并且在这两种情况下,都有以下替换模式 -

replaced

将输出以下内容 -

replaced
replaced
replaced
exec.exe    200

另外,如果我只更换文件的名称(保持扩展名和大小相同),我可以使用它 -

/(.+)(jpg|png|gif)(\t[\d]+)/g

并使用以下替换模式 -

new name.$2$3

我会得到 -

new name.jpg    100
new name.png    201
new name.gif    102
exec.exe    200

在这种情况下使用非捕获组可以让我通过在替换模式中使用一个较少的变量来完成任务 -

/(.+)((?:jpg|png|gif)\t[\d]+)/g

替换 -

new name.$2

到目前为止,我还没有看到任何必须使用非捕获组的用例,否则将无法实现其功能。我是正确的还是我错过了什么?

注意 -

- 我知道使用正则表达式可以有多种方法来解决问题。如果问题的解决方案中只有一个涉及非捕获组,我仍然认为它是一个有效的方案,因为以特定方式解决需要非捕获组。

- 为了解释用例,您可能会演示一个不同的问题。

2 个答案:

答案 0 :(得分:0)

如果您的文件名必须包含“one”,“two”或“three”,该怎么办?

one-file.jpg   100
file-two.png    201
other-file.gif   102
three-file.exe    200

现在非捕获组很有用

/.*(?:one|two|three).*\.(jpg|png|gif)(\t[\d]+)/g

答案 1 :(得分:0)

您也可以始终使用常规捕获括号来实现群集。假设您在正则表达式本身中没有使用back-references ,那么正确的任何正则表达式将失败/成功匹配,基于捕获与非捕获括号的选择: / p>

/((hello) (world)) \1/     //=>\1 equals "hello world" (pattern matches 'hello world hello world')
/((hello) (world)) \2/     //=>\2 equals "hello" (pattern matches 'hello world hello')
/((hello) (world)) \3/     //=>\3 equals "world" (pattern matches 'hello world world')
/(?:(?:hello)) (world) \2/   //=>\2 does not exist, pattern fails.(only \1 exists and equals 'world'

您决定如何分组/捕获也会影响生成的匹配对象。如果您的目标是解析输入,那么成功匹配是不够的。

考虑字符串" 3 / 0.125" - 您希望将此算术运算拆分为它的成分标记:3,/和0.125。

正则表达式的3个变体来执行此操作:

1)包含两个命名组和非捕获组:

(?<operand1>(?:\d+(?:\.\d+)?)|(?:\.\d+))(?<operator>[+\/\*-])(?<operand2>(?:\d+(?:\.\d+)?)|(?:\.\d+))

enter image description here

2)或没有命名组:

((?:\d+(?:\.\d+)?)|(?:\.\d+))([+\/\*-])((?:\d+(?:\.\d+)?)|(?:\.\d+))

enter image description here

3)没有命名或非捕获组:

((\d+(?:\.\d+)?)|(\.\d+))([+\/\*-])((\d+(\.\d+)?)|(\.\d+))

enter image description here

显然你的输出,更不用说正则表达式本身,当你只是按常规()滚动时,它是不是很明智。