AWK:如何在 gensub() 函数的正则表达式字段中有反向引用 \1?

AWK: how to have backreference \1 in gensub() function's regex field?

我有以下模式:

$ echo -e "1>1>659,659>659>660\n1>1>683,683>683>684\n1>1>712,712>712>713\n1>1>1080648,1>1>1080660\n1>1>1081100,1>1>1081114"
1>1>659,659>659>660
1>1>683,683>683>684
1>1>712,712>712>713
1>1>1080648,1>1>1080660
1>1>1081100,1>1>1081114

我想替换在逗号和大于号 (>) 之间连续出现相同数字的模式。所以,为了识别 grep 我会这样做:

$ echo -e "1>1>659,659>659>660\n1>1>683,683>683>684\n1>1>712,712>712>713\n1>1>1080648,1>1>1080660\n1>1>1081100,1>1>1081114" |
grep -Eo "([0-9]+),>"

659,659>659
683,683>683
712,712>712

这是对同一组的两个反向引用。

我知道在 awk 中使用 gensub() 我可以在替换字段中有反向引用。但是我怎么能在正则表达式字段中拥有它呢?像这样:

result = gensub(/([0-9]+),\1>\1/,"my replaced string", "g", string)

我怎样才能做到这一点?

这里有一个 sed 的解决方案。

sed 's|\([0-9]\+\),>|Replaced string|g'

echo -e "1>1>659,659>659>660\n1>1>683,683>683>684\n1>1>712,712>712>713\n1>1>1080648,1>1>1080660\n1>1>1081100,1>1>1081114" | sed 's|\([0-9]\+\),>|Replaced string|g'
1>1>Replaced string>660
1>1>Replaced string>684
1>1>Replaced string>713
1>1>1080648,1>1>1080660
1>1>1081100,1>1>1081114

希望你能接受 sed 而不是 awk

但是如果 awk 是强制性的,这里是一个笨拙的 awk 脚本。

awk -F "[>,]" '{sub(","">","Replaced string")}1'

echo -e "1>1>659,659>659>660\n1>1>683,683>683>684\n1>1>712,712>712>713\n1>1>1080648,1>1>1080660\n1>1>1081100,1>1>1081114" | awk -F "[>,]" '{sub(","">","Replaced string")}1'
1>1>Replaced string>660
1>1>Replaced string>684
1>1>Replaced string>713
1>1>1080648,1>1>1080660
1>1>1081100,1>1>1081114

如果您想验证第三个字段始终为数字。 添加以下条件:

awk -F "[>,]" ' ~ "^[0-9]+$"{sub(","">","Replaced string")}1'

Awk 不支持正则表达式中的反向引用,因为这样做需要比 awk 使用的正则表达式引擎慢得多的正则表达式引擎(请参阅 https://swtch.com/~rsc/regexp/regexp1.html),这不是必需的,也很少需要。这可能是你想要做的,使用 GNU awk 作为第三个参数来匹配():

$ awk 'match([=10=],/([0-9]+),/,a){ sub(a[1]","a[1]">"a[1],"my replaced string") } 1' file
1>1>my replaced string>660
1>1>my replaced string>684
1>1>my replaced string>713
1>1>1080648,1>1>1080660
1>1>1081100,1>1>1081114

或使用任何 awk:

$ awk 'match([=11=],/([0-9]+),/){ a=substr([=11=],RSTART,RLENGTH-1); sub(a","a">"a,"my replaced string") } 1' file
1>1>my replaced string>660
1>1>my replaced string>684
1>1>my replaced string>713
1>1>1080648,1>1>1080660
1>1>1081100,1>1>1081114