关于gawk中gensub替换的算法

时间:2018-01-14 00:08:31

标签: awk gawk

我想知道以下是否可行:

echo -e "0@1 1@1 0@0\n0@0 1@1 0@1" | awk '{print gensub(/([01])@([01])/, "\\1" + "\\2", "g")}'

它不会像现在这样运作;是因为“+”的评价发生在“\ 1”和“\ 2”的替换之前?

作为输出,我希望1,算术的结果在\ 1和\ 2上,所以对于\ 1 = 0和\ 2 = 1,输出应为1.

另外,根据下面的答案,我不是在寻找如何在“1 @ 0”中添加1和0的解决方案;这只是一个例子,我只是想知道是否可以对\ 1和\ 2进行算术运算,因为这样可行: gensub(/blah blah/, 0 + 1, "g")提供1

4 个答案:

答案 0 :(得分:2)

您无法使用gensub(),因为它会将捕获的组作为文字字符串返回。

对于这样一个微不足道的要求,使用@作为字段分隔符并进行算术运算

echo "0@1" | awk -F@ '{print ($1 + $2)}'

或者,如果您担心输入字符串中的字符串值,请使用int()强制转换强制数字转换,或者只为每个操作数添加+0,即使用(int($1) + int($2))(($1+0) + ($2+0))

根据下面答案中更新的问题/评论,进行常数数字运算不是gensub()的用途,应该进行基于正则表达式的模式搜索和替换。大多数情况下的替换部分涉及从搜索字符串处理捕获的组并对其应用一些修改。

答案 1 :(得分:1)

我想我明白你想要什么,你可以在Perl中使用替换上的e修饰符来实现它,这意味着它会评估替换。这是一个例子:

echo "7@302" | perl -nle 's/(\d+)@(\d+)/$1+$2/e && print'
309

或者,更有趣:

echo "The 200@109 cats sat on the 7@302 mats" | perl -nle 's/(\d+)@(\d+)/$1+$2/ge && print'
The 309 cats sat on the 309 mats

答案 2 :(得分:1)

您可以使用sed w / bc进行计算,就像Mark使用perl一样:
echo "7@302" | sed -E 's/([0-9]+)@([0-9]+)/echo "\1+\2"|bc/e'

答案 3 :(得分:0)

当你写foo(bar())时,你会发现bar()首先被执行,无论它是一个函数还是任何表达式,所以gensub(..., "\\1" + "\\2", ...)使用添加的结果调用gensub() 2个字符串0,即gensub(..., 0, ...)

这与您编写的代码在语义上不相同,但方法可以使用第3个arg到match()

$ echo "0@1" | awk 'match($0,/([01])@([01])/,a){print a[1] + a[2]}'
1

以上使用GNU awk将第3个arg用于match(),但无论如何你已经在gensub()使用了它。如果不清楚如何在您的真实数据上使用它,那么发布一个包含您的真实数据示例的后续问题。