gawk 中 gensub 替换的算法
Arithmetic on gensub substitution in 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
.
您不能为此使用 gensub()
,因为它 returns 捕获的组作为其结果的文字字符串。
对于这样一个琐碎的需求,使用@
作为字段分隔符并进行算术计算
echo "0@1" | awk -F@ '{print ( + )}'
或者如果您担心输入字符串中的字符串值,请使用 int()
转换强制进行数字转换,或者只需将 +0
添加到每个操作数,即使用 (int() + int())
或 ((+0) + (+0))
根据下面答案中更新的 question/comments,gensub()
不打算进行常量数字运算,它应该进行基于正则表达式的模式搜索和替换。大多数情况下的替换部分涉及处理从搜索字符串中捕获的组并对其应用一些修改。
我想我明白你想要什么,你可以在 Perl 中对替换使用 e
修饰符来完成,这意味着它会评估替换。这是一个例子:
echo "7@302" | perl -nle 's/(\d+)@(\d+)/+/e && print'
309
或者,稍微有趣一点:
echo "The 200@109 cats sat on the 7@302 mats" | perl -nle 's/(\d+)@(\d+)/+/ge && print'
The 309 cats sat on the 309 mats
当你写foo(bar())
时,你会发现bar()
无论是函数还是任何表达式都会先执行,所以gensub(..., "\1" + "\2", ...)
调用gensub()
使用的结果添加 0
的 2 个字符串,即 gensub(..., 0, ...)
.
这在语义上与您编写的代码不相同,但是 方法 执行您想要的操作是使用第三个参数 match()
:
$ echo "0@1" | awk 'match([=10=],/([01])@([01])/,a){print a[1] + a[2]}'
1
以上使用 GNU awk 作为 match()
的第 3 个参数,但无论如何您已经将其用于 gensub()
。如果不清楚如何在您的真实数据上使用它,那么 post 一个包含真实数据示例的后续问题。
您可以使用 sed w/bc 进行计算,就像 Mark 使用 perl 的方式:
echo "7@302" | sed -E 's/([0-9]+)@([0-9]+)/echo "+"|bc/e'
请问是否可以:
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
.
您不能为此使用 gensub()
,因为它 returns 捕获的组作为其结果的文字字符串。
对于这样一个琐碎的需求,使用@
作为字段分隔符并进行算术计算
echo "0@1" | awk -F@ '{print ( + )}'
或者如果您担心输入字符串中的字符串值,请使用 int()
转换强制进行数字转换,或者只需将 +0
添加到每个操作数,即使用 (int() + int())
或 ((+0) + (+0))
根据下面答案中更新的 question/comments,gensub()
不打算进行常量数字运算,它应该进行基于正则表达式的模式搜索和替换。大多数情况下的替换部分涉及处理从搜索字符串中捕获的组并对其应用一些修改。
我想我明白你想要什么,你可以在 Perl 中对替换使用 e
修饰符来完成,这意味着它会评估替换。这是一个例子:
echo "7@302" | perl -nle 's/(\d+)@(\d+)/+/e && print'
309
或者,稍微有趣一点:
echo "The 200@109 cats sat on the 7@302 mats" | perl -nle 's/(\d+)@(\d+)/+/ge && print'
The 309 cats sat on the 309 mats
当你写foo(bar())
时,你会发现bar()
无论是函数还是任何表达式都会先执行,所以gensub(..., "\1" + "\2", ...)
调用gensub()
使用的结果添加 0
的 2 个字符串,即 gensub(..., 0, ...)
.
这在语义上与您编写的代码不相同,但是 方法 执行您想要的操作是使用第三个参数 match()
:
$ echo "0@1" | awk 'match([=10=],/([01])@([01])/,a){print a[1] + a[2]}'
1
以上使用 GNU awk 作为 match()
的第 3 个参数,但无论如何您已经将其用于 gensub()
。如果不清楚如何在您的真实数据上使用它,那么 post 一个包含真实数据示例的后续问题。
您可以使用 sed w/bc 进行计算,就像 Mark 使用 perl 的方式:
echo "7@302" | sed -E 's/([0-9]+)@([0-9]+)/echo "+"|bc/e'