不是答案,只是为了展示一种更简洁、惯用的方式来根据相关 cmets 中讨论的 @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() 中的 char 映射到它下面的 char(s) 并且对于您想要的任何其他映射,您只需要更改 string(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,那不是很好吗?以上确实是最好的方法,但当然是你的电话。
这是一个完整的解决方案,如下面的 cmets 中讨论的那样
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 只是因为 iMHO 更能代表数组的用途。
将上述内容保存在文件script.awk 中并以awk -f script.awk inputfile 运行它