我的 awk 脚本从 读取记录file1
,在 中找到相同的记录,file2
并用其中定义的符号替换(记录的)替代位置。但很少有值没有按预期被替换。只有该单词的第一个实例被替换,例如
TYTYTY
进入T##Y##
TYTYTYGGHG
进入T##Y##GGHG
LEFT
进入L##T
LEFT NAME
进入L##T NAME
预期输出如下。
我的代码-
awk ' FNR==NR
{
if ($0 in word)
next
word[$0]=$0
for (i=1;i<=NF;i++)
{
old=$i
new=""
while (old) {
len=length(old)
new=new substr(old,1,1) substr("##",1,len-1)
old=substr(old,4)
}
id=index(word[$0],$i)
word[$0]=substr(word[$0],1,id-1) new substr(word[$0],id+length($i))
}
next
}
{
for (i in word)
{
regex = "\\<" i "\\>"
gsub(regex, ext[i])
#id=index($0,i)
#while(id>0) {
#$0=substr($0,1,id-1) word[i] substr($0,id+length(word[i]))
#id=index($0,i)
}
}
print
}' records test.html > output.html
$ cat records
LEFT NAME
LEFT NAME 2
LEFT
LEFT 123
TYTYTYGGHG
TYTYTY
AB 8263
AB SCENARIO DEBUG
AB 8263 SCENARIO DEBUG
$ 猫测试.html
<html>
<body>
<hr><br><>span class="table">TabA</span><table>
<tr class="column">
<td>LEFT NAME</td>
<td>LEFT</td>
<td></td>
<td>LEFT NAME 2</td>
<td>LEFT 123</td>
<td>TYTYTYGGHG</td>
<td></td>
<td>TYTYTY</td>
</tr>
<tr class="data">
<td></td>
<td></td>
<td></td>
<td>AB 8263</td>
<td></td>
<td></td>
<td>AB SCENARIO DEBUG</td>
<td>AB 8263 SCENARIO DEBUG</td>
</tr>
</table>
</body>
</html>
所需的操作 -
<html>
<body>
<hr><br><>span class="table">TabA</span><table>
<tr class="column">
<td>L##T N##E</td>
<td>L##T</td>
<td></td>
<td>L##T N##E 2</td>
<td>L##T 1##</td>
<td>T##Y##G##G</td>
<td></td>
<td>T##Y##</td>
</tr>
<tr class="data">
<td></td>
<td></td>
<td></td>
<td>A# 8##3</td>
<td></td>
<td></td>
<td>A# S##N##I# D##U#</td>
<td>A# 8##3 S##N##I# D##U#</td>
</tr>
</table>
</body>
</html>
电流输出-
<html>
<body>
<hr><br><>span class="table">TabA</span><table>
<tr class="column">
<td>L##T NAME</td>
<td>L##T</td>
<td></td>
<td>L##T NAME 2</td>
<td>L##T 123</td>
<td>T##Y##GGHG</td>
<td></td>
<td>T##Y##</td>
</tr>
<tr class="data">
<td></td>
<td></td>
<td></td>
<td>A# 8##3</td>
<td></td>
<td></td>
<td>A# S##N##I# D##U#</td>
<td>A# 8##3 SCENARIO DEBUG</td>
</tr>
</table>
</body>
</html>
答案1
我很惊讶这不是一个骗局,不过https://stackoverflow.com/questions/34375020/why-the-output-of-array-using-awk-is-not-in-right-order非常接近。
总括:awk 数组没有排序(一般来说)
当您使用 awk 中的数组进行迭代时,for (i in word)
返回“索引”值(也称为下标或键)的顺序是未指定经过标准;传统上,这些数组被实现为哈希表,并按照该哈希表的顺序进行迭代,该哈希表是某个哈希码对某个值取模,在发生冲突时可能会被修改或重新哈希(所谓的“封闭哈希”)。这与插入条目/键的顺序不同,通常它是确定性的,但足够复杂,从人类的角度来看似乎是随机的。
因此,在您的示例中,根据您使用的 awk 和您的确切数据,循环很有可能在处理之前for
处理条目;结果,包含匹配的行被更改为,随后当循环尝试不匹配时,该行不会进一步更改。同样,不匹配的先处理,不匹配的先处理。在不同的 awk 上运行或使用不同的 file1 数据运行很可能会产生不同的顺序,从而产生不同的结果;在不同的环境中运行可能会这样做。LEFT
LEFT NAME
LEFT NAME
LEFT
L##T NAME
LEFT NAME
TYTYTY
TYTYTYGGHG
AB 8263
AB 8263 SCENARIO DEBUG
同样在您的FNR==NR
(即 file1)分支中,new-new substr(old,1,1) substr("##",1,len-1)
需要=
不是-
.就我个人而言,我发现制作该子循环更自然
old=$i; new=""; for(c=1; c<=length(old); c++) new = new (c%3==1? substr(old,c,1): "#")
虽然差异很小。尽管您应该知道您的子循环,但如果 file1 中的任何单词完全由一个或多个0
数字组成,可选地在+
或之前,-
并且可选地后跟e
和 任何数字,会将其更改为空字符串,而不是相同长度的屏蔽版本。