Linux shell的音译脚本

我有多个.txt文件包含字母表中的文本; 我想把文字音译成另外一个字母; 字母1的一些字符与字母2的字符是1:1(即a变成e ),而另一些字符是1:2(即x变成ch )。

我想用Linux shell的一个简单的脚本做这个。

TRSED我可以转换1:1字符:

sed -fy/abcdefghijklmnopqrstuvwxyz/nopqrstuvwxyzabcdefghijklm/ 

a会变成nb会变成o等等(我认为是凯撒的密码)

但是我怎样才能处理1:2的字符?

Solutions Collecting From Web of "Linux shell的音译脚本"

不是一个答案,只是为了显示一个简单的,习惯于从@ konsolebox的答案填充table[]数组的方法,如相关注释中所讨论的:

 BEGIN { split("aeb", old) split("x ch o", new) for (i in old) table[old[i]] = new[i] FS = OFS = "" } 

所以旧字符到新字符的映射清楚地表明,第一个split()中的char映射到它下面的char(s),对于任何其他您想要的映射,您只需更改其中的字符串split()不改变对table []的26个显式赋值。

您甚至可以创建一个通用脚本来完成映射,只需将新旧字符串作为变量传递即可:

 BEGIN { split(o, old) split(n, new) for (i in old) table[old[i]] = new[i] FS = OFS = "" } 

然后在shell里这样的东西:

 old="aeb" new="x ch o" awk -vo="$old" -vb="$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("aeb", 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输入文件运行

使用Awk:

 #!/usr/bin/awk -f BEGIN { FS = OFS = "" table["a"] = "e" table["x"] = "ch" # and so on... } { for (i = 1; i <= NF; ++i) { if ($i in table) { $i = table[$i] } } } 1 

用法:

 awk -f script.awk file 

测试:

 # echo "the quick brown fox jumps over the lazy dog" | awk -f script.awk the quick brown foch jumps over the lezy dog 

这可以用Perl一行简单的完成:

 perl -pe '%h=(a=>"xy",c=>"z"); s/(.)/defined $h{$1} ? $h{$1} : $1/eg' 

或相当( 谢谢jaypal ):

 perl -pe '%h=(a=>"xy",c=>"z"); s|(.)|$h{$1}//=$1|eg' 

%h是包含字符(键)及其替换(值)的散列。 s是替代命令(如sed)。 g修饰符表示替换是全局的, e表示替换部分被评估为表达式。 它将逐个捕获每个字符,如果它存在,则用它们中的值替换它们,否则保持原始值。 -p开关意味着输入中的每一行都会自动打印。

测试一下:

 $ perl -pe '%h=(a=>"xy",c=>"z"); s|(.)|$h{$1}//=$1|eg' <<<"abc" xybz