sed 正则表达式文本处理捕获分组引用交替混乱

sed 正则表达式文本处理捕获分组引用交替混乱

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被替换为无任何内容,并且aefgg和保持不变,因此您会得到_预期的结果。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)。

这种方法没有放大代码。有时你只需要采取不同的做法。当然,您也可以使用组而不只是字符来执行此操作。

但是,如果这不能解决您的实际问题(并且您不知道如何适应它),请用示例数据告诉我们您的实际问题。

相关内容