我有多个包含字母表文本的 .txt 文件;我想将文本音译成其他字母;字母表 1 的某些字符与字母表 2 的字符是 1:1(即 a 变为 e),而其他字符是 1:2(即 x 变为 ch)。
我想使用一个简单的 Linux shell 脚本来做到这一点。
使用 tr 或 sed 我可以转换 1:1 字符:
sed -f y/abcdefghijklmnopqrstuvwxyz/nopqrstuvwxyzabcdefghijklm/
a 会变成 n,b 会变成 o 等等(我认为是凯撒密码)
但是我该如何处理 1:2 字符呢?
最佳答案
不是答案,只是为了展示一种更简洁、惯用的方式来从@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() 中的字符被映射到它下面的字符,对于任何其他你想要的映射,你只需要更改字符串中的字符串split(),不会改变对 table[] 的 26-ish 显式赋值。
您甚至可以创建一个通用脚本来进行映射,并将旧字符串和新字符串作为变量传入:
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
只是因为 iMHO 更能代表数组的用途。将上述内容保存在
script.awk
文件中并作为 awk -f script.awk inputfile
运行关于linux - linux shell的音译脚本,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/25338470/