我有多个包含字母表文本的 .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/

10-11 22:09
查看更多