awk循环中删除元素:POSIX标准规定的预期行为及实现差异
Awk for-in循环中删除元素的POSIX标准行为探讨
假设awk的for-in循环先返回k==0(按键遍历顺序由实现决定),请问循环体应执行一次还是两次?若执行两次,arr[1]应输出什么?
测试代码如下:
BEGIN { arr[0] = "zero"; arr[1] = "one"; for (k in arr) { print "key " k " val " arr[k]; delete arr[k+1] } }
不同awk实现的运行结果存在差异:
- GNU Awk 5.1.0执行两次,arr[1]输出空字符串;
- goawk v1.19.0仅执行一次;
- mawk 1.3.4遍历顺序为1、0,但同样执行两次,已删除的键输出空字符串。
核心问题:该程序的POSIX标准定义的预期行为是什么?本质是循环中已删除的键是否应出现在后续循环中?
标准解读与结论
根据POSIX对awk的规范,for-in循环的遍历集合是在循环开始前就确定好的——也就是循环启动时数组中所有已存在的键的集合。哪怕在循环体内删除或新增数组元素,都不会改变这个预先确定的遍历集合。
回到假设场景:循环启动时arr包含0和1两个键,因此遍历集合固定为{0,1},不管循环中是否删除arr[1],循环都会执行两次。
当遍历到k=1时,由于之前在k=0的循环体中已经执行了delete arr[1],此时arr[1]已不存在,而awk中访问不存在的数组元素会返回空字符串,所以arr[1]的输出为空。
需要注意的是,POSIX并未强制规定for-in循环的遍历顺序,不同awk实现可以采用不同的顺序,但循环执行次数由循环启动时的键集合决定这一点是明确的。
内容的提问来源于stack exchange,提问作者nlta
相关产品推荐
相关产品推荐

