你如何在sed中指定非捕获组?

时间:2011-01-28 01:19:30

标签: linux command-line sed

是否可以在sed中指定非捕获组?

若然,怎么样?

3 个答案:

答案 0 :(得分:28)

圆括号可用于分组替代品。例如:

sed 's/a\(bc\|de\)f/X/'

说取代" abcf" " adef"使用" X",但括号捕获。 sed中没有设施可以进行此类分组而无需捕获。如果你有一个复杂的正则表达式同时进行替代分组捕获,你只需要在替换中选择正确的捕获组时要小心。

也许您可以更多地了解您正在尝试完成的事项(您对非捕获组的需求是什么)以及您希望避免捕获组的原因。

修改

有一种非捕获括号((?:pattern))是Perl-Compatible Regular Expressions(PCRE)的一部分。 sed不支持它们(但使用grep -P时)。

答案 1 :(得分:3)

我假设你说的是反驳语法,它是括号( )而不是括号[ ]

默认情况下,sed会按字面解释( ),而不会尝试对其进行反馈。您将需要转义它们以使其特殊,如\( \)只有当您使用GNU sed -r选项时才会撤消转义。使用sed -r时,非转义( )将生成回溯,转义\( \)将被视为文字。要遵循的例子:

POSIX sed

$ echo "foo(###)bar" | sed 's/foo(.*)bar/@@@@/'
@@@@

$ echo "foo(###)bar" | sed 's/foo(.*)bar/\1/'
sed: -e expression #1, char 16: invalid reference \1 on `s' command's RHS
-bash: echo: write error: Broken pipe

$ echo "foo(###)bar" | sed 's/foo\(.*\)bar/\1/'
(###)

GNU sed -r

$ echo "foo(###)bar" | sed -r 's/foo(.*)bar/@@@@/'
@@@@

$ echo "foo(###)bar" | sed -r 's/foo(.*)bar/\1/'
(###)

$ echo "foo(###)bar" | sed -r 's/foo\(.*\)bar/\1/'
sed: -e expression #1, char 18: invalid reference \1 on `s' command's RHS
-bash: echo: write error: Broken pipe

更新

来自评论:

仅限群组,非捕获括号( ),因此您可以使用区间{n,m}之类的内容而不创建反向引用\1。首先,间隔不是POSIX sed的一部分,您必须使用GNU -r扩展来启用它们。一旦启用-r,任何分组括号也将捕获反向引用。例子:

$ echo "123.456.789" | sed -r 's/([0-9]{3}\.){2}/###/'
###789

$ echo "123.456.789" | sed -r 's/([0-9]{3}\.){2}/###\1/'
###456.789

答案 2 :(得分:1)

如上所述,sed中不可能有非捕获组。 这可能是显而易见的,但非捕获组并非必需品。可以使用所需的捕获并忽略非期望的捕获,就好像它们是非捕获的一样。作为参考,嵌套捕获组按照"("。

的位置顺序编号

,例如,

echo "apple and bananas and monkeys" | sed -r "s/((apple|banana)s?)/\1x/g"

applex和香蕉 s x和猴子(注意:" s"在香蕉中,第一个更大的群体)

VS

echo "apple and bananas and monkeys" | sed -r "s/((apple|banana)s?)/\2x/g"

applex和bananax和猴子(注意:没有" s"在香蕉,第二小组)