是否可以在sed中指定非捕获组?
若然,怎么样?
答案 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
时,非转义( )
将生成回溯,转义\( \)
将被视为文字。要遵循的例子:
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/'
(###)
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"在香蕉,第二小组)