为何GNU AWK的sub函数未对选中字段生效?如何保留间距替换字段
AWK字段替换问题:仅替换独立字段并保留空格
AWK能正确识别字段,哪怕字段间有多个空格:
$ printf "a ab c d b" | awk '{for (i=1;i<=NF;i++) print $i}' a ab c d b $ printf "a ab c d b" | awk '{for (i=1;i<=NF;i++) if ($i=="b") print $i}' b
注意c前面有3个空格。但直接用sub替换时,会错误命中包含b的字段(比如ab里的b):
$ printf "a ab c d b" | awk '{for (i=1;i<=NF;i++) if ($i=="b") sub($i,"X"); print}' a aX c d b
下面是几种解决方法:
方法1:拆分字段与分隔符后拼接(保留原始空格)
利用AWK的split函数(GNU AWK、mawk支持),拆分时同时保存字段和分隔符数组,替换目标字段后再拼接回去:
printf "a ab c d b" | awk '{ n = split($0, fields, /([[:space:]]+)/, seps) for (i=1; i<=n; i++) { if (fields[i] == "b") fields[i] = "X" } for (i=1; i<=n; i++) { printf "%s%s", fields[i], seps[i] "" } print "" }'
执行后输出:a ab c d X,完美保留了c前的3个空格,且只替换了独立的b字段。
方法2:用单词边界正则直接替换(GNU AWK专属)
如果用GNU AWK,可以借助单词边界\y匹配独立的b,用gensub全局替换:
printf "a ab c d b" | awk '{print gensub(/\yb\y/, "X", "g")}'
这个方法更简洁,同样能得到正确结果,缺点是仅支持GNU AWK,其他AWK版本可能不识别\y。
内容的提问来源于stack exchange,提问作者user2138595
相关产品推荐
相关产品推荐

