使用bash将字符串翻译成另一种语言

时间:2017-05-09 00:03:31

标签: bash translate letters latin

我创建了一个脚本,可以获取拉丁语和希腊语中人物的姓名和姓氏。我的挑战是将所有希腊字符翻译成拉丁字符,以便创建更多可能的Facebook链接到他们的个人资料,但只使用bash而已,如python,ruby等。

我创建了类似哈希表文件的内容,如下所示(如下所示)并遵循一个简单的规则...每个记录用逗号分隔,第一个字段代表数字字母表达的其他表达方式,第二字段代表我想要找到的 greek 字母和下一个字母( 3rd < / strong>和/或 4th )表示希腊字母以拉丁语方式表达的方式。

0,Α,A
0,Β,B
0,Γ,G
0,Δ,D
0,Ε,E
0,Ζ,Z
0,Η,I
0,Θ,TH
0,Ι,I
0,Κ,K
0,Λ,L
0,Μ,M
0,Ν,N
1,Ξ,X,KS
0,Ο,O
0,Π,P
0,Ρ,R
0,Σ,S
0,Τ,T
1,Υ,Y,U
1,Φ,F,PH
1,Χ,CH,H
0,Ψ,PS
1,Ω,O,W

现在,经过数小时的研究,我找不到任何符合我需求的东西。 我尝试过但没有成功的是将一个字符串传递给函数,然后函数加载它必须从它的散列表中转换的每个字母,然后将它输出到一个名为 data的文件中.tr

function greek2latin()
{
 #usage: greek2latin <string>
        while read hashed
        do
            greek=$(echo $hashed | cut -d',' -f2)
            latin0=$(echo $hashed | cut -d',' -f3)

            echo $1 | tr '$greek' '$latin0' > "$PWD"/data/data.tr

            #note that "1" is read as string, thus compared as one
            #maybe I need to change that later on
            if [ $(echo "$hashed" | cut -d',' -f1) == "1" ]
            then
                latin1=$(echo $hashed | cut -d',' -f4)
                echo $1 | tr '$greek' '$latin1' > "$PWD"/data/data.tr
            fi 

        done < "$PWD"/data/hashed.synonyms/greek2latin
}

有人能告诉我为什么它没有按预期工作吗?我很感激任何帮助。

  

谢谢! :)

1 个答案:

答案 0 :(得分:2)

(0)初步,用语言A中的单词并将每个字母(或有时字母对)更改为字母(或对)与语言B中的(近似)相同的声音,但不更改为语言B中的单词,不是翻译,而是音译。还有你的桌子&#39;文件没有散列或散列;它只是一个包含所需翻译的文件。

(1)你的脚本没有改变任何东西,因为shell变量没有在单引号内扩展;实际上根本没有任何内容在单引号中具有特殊含义,由this quite terse item in the bash manual指定:

  

用单引号括起字符('&#39;')会保留引号中每个字符的字面值。单引号之间可能不会出现单引号,即使前面有反斜杠也是如此。

因此,您告诉tr$替换为$,将g替换为l,将r替换为a },e ik n。由于您的输入可能不包含任何$ g r e k,因此无效。

(2A)如果你通过使用扩展$var的双引号(以及其他一些不相关的东西)来解决这个问题,那么在某些情况下它仍然无法工作,因为 {{1 }逐字符替换。因此,如果您使用第一个参数xi(一个char,请参阅下一个)和第二个参数tr(两个字符)运行tr,它会将任何(和所有)xi转换为KS并且永远不会使用什么都有K

要将单个字符转换为可能包含多个字符的字符串,请考虑使用S或类似sedawk的字符。或者因为你只想要抨击&#39;你可以使用bash自己的字符串替换,如perl

(2B)另一个可能的问题是,许多(但绝不是全部)具有GNU shell ${1//$greek/$latin}的系统也具有 GNU coreutils bash实现不支持多字节字符,即UTF-8。大多数多语种&#39; (更准确地说,非英语/非ASCII)材料现在用UTF-8编码。但是有一个ISO-8859 single-octet code, variant -7, for Greek,如果您的输入(脚本和数据)在8859-7中或者可以转换为那个,那么除了多字符情况外,GNU tr可以使用。

(3)您不需要多个tr进程来解析输入行; shell cut可以做到:

read

(4)while IFS=, read flag greek latin0 latin1; do echo "${1//$greek/$latin0}" >>output if [ "$flag" == "1" ]; then echo "${1//$greek/$latin1}" >>output; fi done <translationsfile 可能会因某些数据而出现故障,尽管这些数据可能不太适合您的用例。 The safer and more portable method is printf.

(5)你真的不需要标志栏告诉你什么时候拉丁1&#39;列存在,您可以只测试echo的值(非空)。

(6)你的逻辑为每个字母创建一个单独的翻译,或者两个。如果输入名称有例如没有重复的5个字母,你将创建5个翻译,每个翻译只有一个字母从希腊语改为拉丁语,另外20个字母或其他任何字母(我没有计算),完全没有变化。我经常看到人们使用所有字母的名称音译成不同的语言,这对于至少一些人来说可能更方便,但是一种语言中的一些字母和另一种语言中的一个字母的名称似乎让我不方便每个人因此无用。我将从输入名称开始,并音译所有字母 - 或者是值中的所有字母(可能带有实际的哈希表,可以在最近的bash中使用关联数组实现)或者全部可能的。我离开了这个,所以你仍然可以为你的任务完成一些工作。

(7)最后也是最不重要的,你永远不需要指定$latin1作为文件的起始路径,因为相对路径名自动在工作目录中开始;这是什么&#39;工作目录&#39; 装置。如果你想强调它是相对的,一个常见的约定是从$PWD开始,这在技术上仍然是多余的,但是是一个明显的提醒。