问题:在window上保存ANSI格式文本文件,复制到liunx系统,其中的中文乱码。

常规解决办法

1. 查看文本文件的编码

  1. [root@localhost example]# file -i 7-2.c
  2. 7-2.c: text/x-c; charset=iso-8859-1

2. 利用iconv命令进行转码

  1. [root@localhost example]# iconv -f iso-8859-1 -t utf-8 7-2.c
  2. #include <stdio.h>
  3. /*
  4. ÀûÓÃÊý×é¼ÆËãì³²¨ÄÇÆõÊýÁеÄÇ°10¸öÊý
  5. ¼´ 1,1,2,3,5,...,55 ²¢°´ÕÕÿÐÐ5¸öÊýµÄ¸ñʽÊä³ö
  6. */
  7. int main()
  8. {
  9. int list[10] = {1,1};
  10. int i;
  11. for(i=2; i<10; i++) {
  12. list[i] = list[i-1] + list[i-2];
  13. }
  14. for(i=0; i<10; i++) {
  15. printf("%d\t", list[i]);
  16. if ((i+1)%5 == 0) {
  17. printf("\n");
  18. }
  19. }
  20. return 0;
  21. }

可见,仍然是乱码!!!

这里边的坑

file命令识别文件的编码不正确
我这个文件的正确编码应该是GBK

  1. [root@localhost example]# iconv -f GBK -t utf-8 7-2.c
  2. #include <stdio.h>
  3. /*
  4. 利用数组计算斐波那契数列的前10个数
  5. 即 1,1,2,3,5,...,55 并按照每行5个数的格式输出
  6. */
  7. int main()
  8. {
  9. int list[10] = {1,1};
  10. int i;
  11. for(i=2; i<10; i++) {
  12. list[i] = list[i-1] + list[i-2];
  13. }
  14. for(i=0; i<10; i++) {
  15. printf("%d\t", list[i]);
  16. if ((i+1)%5 == 0) {
  17. printf("\n");
  18. }
  19. }
  20. return 0;
  21. }

可见,转码成功!

两个问题

有没有能够准确识别文件编码的工具?如果没有,能不能自己写一个?

批量转码脚本

  1. # 设置调试参数 │[root@localhost data]# ls
  2. set -ueEo pipefail; 7-2.c 7-3.c 7-4.c 7-5.c 7-6.c
  3. #读取参数 │[root@localhost data]# bash mutil-iconv.sh -f gbk -t utf-8 data/*.c
  4. while getopts ":f:t:" OPT; do bash: mutil-iconv.sh: No such file or directory
  5. case "$OPT" in │[root@localhost data]# cd ..
  6. f) │[root@localhost script]# bash mutil-iconv.sh -f gbk -t utf-8 data/*.c
  7. from_code=$OPTARG; data/7-2.c data/7-3.c data/7-4.c data/7-5.c data/7-6.c
  8. ;; │/usr/bin/iconv: illegal input sequence at position 53
  9. t) │/usr/bin/iconv: illegal input sequence at position 40
  10. to_code=$OPTARG; │/usr/bin/iconv: illegal input sequence at position 34
  11. ;; │/usr/bin/iconv: illegal input sequence at position 39
  12. ?) │/usr/bin/iconv: illegal input sequence at position 39
  13. echo "arg err" >&2; │[root@localhost script]# bash mutil-iconv.sh -f gbk -t utf-8 data/*.c
  14. exit 1; data/7-2.c data/7-3.c data/7-4.c data/7-5.c data/7-6.c
  15. ;; │/usr/bin/iconv: illegal input sequence at position 39
  16. esac │[root@localhost script]#
  17. done
  18. # 检查必要的参数 │
  19. if [ -z "$from_code" ]; then
  20. echo "必须传入源文件的编码" >&2;
  21. exit 1;
  22. fi
  23. if [ -z "$to_code" ]; then
  24. echo "必须传入要转换的编码" >&2;
  25. exit 1;
  26. fi
  27. # 读取文件列表 │
  28. shift $((OPTIND-1));
  29. # 读入数组中 │
  30. file_list=($@);
  31. # 循环处理 │
  32. for item in ${file_list[*]}
  33. do
  34. #echo /usr/bin/iconv -f "$from_code" -t "$to_code" -o "$item" "$item"; │
  35. /usr/bin/iconv -f "$from_code" -t "$to_code" -o "$item" "$item";
  36. done

写脚本时遇到的问题-总结

getopts命令

命令也是人用程序写出来的,基本思维是一样的!!!
getopts命令,语法格式
getopts optstring variable [arg]
getopts的作用是,取出-开头的参数列表。optstring就是要取的参数列表,比如”fh”,即
getopts “fh” key。怎么工作的?说白了,看看$1是不是带有-,如果没有命令终止。如果有-, 再看看是否在”fh”中。如果不是报错,终止命令,如果事继续看看$2。就这样,我们自己写也可能这样写。
getopts命令用到了几个全局变量
OPTIND : 当前取到第几个了,也就是${!OPTIND}
OPTARG: “f:”,后面加个冒号表示该参数需要带值,获取的的值就存入OPTARG中
“:fh”,最前边放冒号表示静默模式,如果命令出错不返回错误信息
arg 默认 $@,可以指定。比如 getopts “fh:” var aa cc bb。如下:

  1. [root@localhost script]# getopts "hf:" OPT -h
  2. [root@localhost script]# echo $OPT
  3. h
  4. [root@localhost script]# getopts "hf:" OPT aa bb
  5. [root@localhost script]# echo $OPT
  6. ?
  7. [root@localhost script]#

一种调试方式

  1. #echo /usr/bin/iconv -f "$from_code" -t "$to_code" -o "$item" "$item";
  2. # 可以打印命令最终执行的样子