这不是答案,只是展示@konsolebox答案中讨论相关评论的一种更简明、习惯用语的方法来填充table[]
数组:
BEGIN {
split("a e b", old)
split("x ch o", new)
for (i in old)
table[old[i]] = new[i]
FS = OFS = ""
}
因此,旧字符到新字符的映射在第一个split()中的字符被映射到其下方的字符(s)中清晰地显示出来。对于您想要的任何其他映射,您只需要更改split()中的字符串,而不是更改26个左右的table[]显式赋值。
您甚至可以创建一个通用脚本来进行映射,并将旧字符串和新字符串作为变量传递:
BEGIN {
split(o, old)
split(n, new)
for (i in old)
table[old[i]] = new[i]
FS = OFS = ""
}
那么在shell中可以这样做:
old="a e b"
new="x ch o"
awk -v o="$old" -v b="$new" -f script.awk file
你可以保护自己免受因填充字符串而产生的错误,例如:
BEGIN {
numOld = split(o, old)
numNew = split(n, new)
if (numOld != numNew) {
printf "ERROR: #old vals (%d) != #new vals (%d)\n", numOld, numNew | "cat>&1"
exit 1
}
for (i=1; i <= numOld; i++) {
if (old[i] in table) {
printf "ERROR: \"%s\" duplicated at position %d in old string\n", old[i], i | "cat>&2"
exit 1
}
if (newvals[new[i]]++) {
printf "WARNING: \"%s\" duplicated at position %d in new string\n", new[i], i | "cat>&2"
}
table[old[i]] = new[i]
}
}
如果您写下 b 映射到 x ,然后过一会儿又误将 b 映射到 y ,那不是很糟糕吗?上述方法确实是解决这个问题的最佳方式,但当然还要看您的意愿。
以下是评论中讨论的一种完整方案。
BEGIN {
numOld = split("a e b", old)
numNew = split("x ch o", new)
if (numOld != numNew) {
printf "ERROR: #old vals (%d) != #new vals (%d)\n", numOld, numNew | "cat>&1"
exit 1
}
for (i=1; i <= numOld; i++) {
if (old[i] in table) {
printf "ERROR: \"%s\" duplicated at position %d in old string\n", old[i], i | "cat>&2"
exit 1
}
if (newvals[new[i]]++) {
printf "WARNING: \"%s\" duplicated at position %d in new string\n", new[i], i | "cat>&2"
}
map[old[i]] = new[i]
}
FS = OFS = ""
}
{
for (i = 1; i <= NF; ++i) {
if ($i in map) {
$i = map[$i]
}
}
print
}
我将table
数组重命名为map
,因为我认为这更好地代表了数组的目的。
将上述内容保存在一个名为script.awk
的文件中,并使用awk -f script.awk inputfile
来运行它。
split("a e x ch ...",t,/ /); for (i=1; i in t; i+=2) table[t[i]] = t[i+1]
。 - Ed Morton