sed 的捕获分组 ALTERNATION 未按预期工作。
虽然交替的优先级最低,但令人困惑的是:
echo "abcd_aefghi" | sed -r "s/(a)(b)(c)(d)|(a)(e)(f)(g)/\8/g;"
observed result --> _ghi
expected result --> error: invalid reference \8 RHS
a--bcd | # Logical alternation (Not bitwise!!)
#must be different separated logical state processing!!
#not involvement of look behind registered reference grouping Counting!!
a--efg ;
还
sed -r "s/(a)((b)(c)(d)|(e)(f)(g))/\8/;"
observed result --> _ghi
更加混乱如果
sed -r "s/(a)(b)(c)(d)()|((a)(e)(f)(g))/\8/g"
observed result --> _ehi
也更加混乱
sed -r "s/(a)(b)(c)(d)()||||i am Not comment, Whats going here?|||||||((a)(e)(f)(g))/\8/g"
observed result --> _ehi
expected result --> full parsing error, because "||"
最糟糕的是内部分组匹配
echo "aBcB_aCfC" | sed -r "s/(a)((B)(c)(\1)|(C)(f)(\1))/\4/g;"
#Infield twin uppercase's must match!
observed result --> aBcB_aCfC
expected result --> c_f
perl -pe
重复同样的问题!
问题在于引用计数超出了交替范围,而不是在识别交替符号后重置计数。
Fedora 20 上的 sed 版本 4.2.2。
当然,我在这里给出的是非常普遍的基本问题。
真正的脚本是非常复杂的长文本原始解析。
我最初的目标是打印每个交替质量分组中的第四个元素。现在我必须拆分匹配,这会显着增加代码量。
有人可以减少我的困惑吗?
答案1
\x
扩展为第 x 个捕获组中捕获的内容,捕获组根据正则表达式中左大括号的出现情况从左到右编号。
echo "abcd_aefghi" | sed -r "s/(a)(b)(c)(d)|(a)(e)(f)(g)/\8/g;"
1 2 3 4 5 6 7 8
该正则表达式匹配两次。一旦打开abcd
(第 8个捕获组什么也不捕获),一旦打开aefg
,第 8个捕获组捕获 a g
。 Soabcd
被替换为无任何内容,并且aefg
和g
和保持不变,因此您会得到_
预期的结果。hi
_ghi
在:
sed -r "s/(a)(b)(c)(d)()|((a)(e)(f)(g))/\8/g"
1 2 3 4 5 67 8 9 10
你得到了_ehi
,因为现在是第 8组(e)
。
sed -r "s/(a)(b)(c)(d)()||||i am Not comment, Whats going here?|||||||((a)(e)(f)(g))/\8/g"
1 2 3 4 5 67 8 9 10
没有什么不同。除了(虽然不可见),由于||
,在 和 之间会有空匹配,并且最后会出现h
一个i
额外的匹配(还有一些带有perl
)。
根据交替运算符重置数字不会成为一个非常有用的 API。如果您想扩展到示例中交替两侧的第四个捕获组所匹配的内容,您始终可以执行以下操作:
sed -r 's/(a)(b)(c)(d)|(a)(e)(f)(g)/\4\8/g'
1 2 3 4 5 6 7 8
这会给你同样的perl
的:
perl -lpe 's/(?|(a)(b)(c)(d)|(a)(e)(f)(g))/\4/g'
1 2 3 4 1 2 3 4
(where\4
可以扩展为what(d)
或(g)
captured)。
答案2
据我了解,您对给定的答案不满意,因为它使您的代码混乱,无法解决您的实际问题。如果不知道真正的问题,很难帮助你。
要保留每次交替的第四部分,您可能应该采取不同的做法:
sed -r 's/abcd|aefg/\n&/g;s/\n...//g'
用换行符标记每个匹配,并在第二遍中删除带有三个不需要的字符的换行符(这sed
仅适用于 GNU,但您可以对不同的 执行类似的操作sed
)。
这种方法没有放大代码。有时你只需要采取不同的做法。当然,您也可以使用组而不只是字符来执行此操作。
但是,如果这不能解决您的实际问题(并且您不知道如何适应它),请用示例数据告诉我们您的实际问题。