统计GNU awk gensub的替换次数

Count the number of replacements of GNU awk gensub

我有以下 bash 使用 gawk gsub 的代码:

replacedCount=$(gawk -v FILE_TMP="$FILE_TMP" -v OLD="$OLD" -v NEW="$NEW" '{ num += gsub( OLD, NEW ); print [=10=] > FILE_TMP; } END { print num }' "$FILE")

它用NEW替换了OLD的所有实例,并将结果输出到FILE_TMP - 替换的次数被捕获在bash变量中。

是否可以使用 gawk gensub 获得相同的结果?

  1. $FILE 长 182 行。
  2. 有 8 个 $OLD 将被替换为 $NEW

我尝试了几种方法,大多数结果等于 182,因为我想我在计算 $0 的出现次数。

我得到的最接近的是这个:

replacedCount=$(gawk -v FILE_TMP="$FILE_TMP" -v OLD="$OLD" -v NEW="$NEW" '{ num[[=11=]=gensub( OLD, NEW, "G" )]++; print [=11=] > FILE_TMP; } END { for (i in num) print num[i] }' "$FILE")

正确输出到 FILE_TMP。然而 replacedCount 是:

replacedCount='8
1
1
1
1
1
1
8
1
8
8
1
1
1
8
1
1
1
1
1
1
1
1
8
8
1
1
1
8
1
1
8
1
1
1
1
1
1
1
1
8
8
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
8
1
8
1
1
1
8
1
1
8
8
1'

$OLD 上的以下匹配作为执行 gensub 和 "num" 计数器增量的入口:

replacedCount=$(gawk -v FILE_TMP="$FILE_TMP" -v OLD="$OLD" -v NEW="$NEW" 'BEGIN { num=0 }; [=10=] ~ OLD { [=10=]=gensub(OLD,NEW,"G"); num++ }; { print > FILE_TMP }; END { print num }' "$FILE")

如果需要对每个匹配项进行计数(行内多次匹配),我们需要在 gensub() 中丢失 "G" 标志,并将增量和 gensub() 置于 while 循环中。

replacedCount=$(gawk -v FILE_TMP="$FILE_TMP" -v OLD="$OLD" -v NEW="$NEW" 'BEGIN { num=0 }; { while ([=11=] ~ OLD) { [=11=]=gensub(OLD,NEW,1); num++ } }; { print > FILE_TMP }; END { print num }' "$FILE")

gensub() 主要用于简化替换 "Nth" 匹配项或不触及原始匹配项的问题。在这个问题中,修改$0似乎是完全合理和自然的,并且使用gsub()和sub()更简洁明了,如下所示:

replacedCount=$(gawk -v FILE_TMP="$FILE_TMP" -v OLD="$OLD" -v NEW="$NEW" 'BEGIN { num=0 }; [=12=] ~ OLD { gsub(OLD,NEW); num++ }; { print > FILE_TMP }; END { print num }' "$FILE")

... 或 "increment for each match" 版本...

replacedCount=$(gawk -v FILE_TMP="$FILE_TMP" -v OLD="$OLD" -v NEW="$NEW" 'BEGIN { num=0 }; { while ([=13=] ~ OLD) { sub(OLD,NEW); num++ } }; { print > FILE_TMP }; END { print num }' "$FILE")