问题:在window上保存ANSI格式文本文件,复制到liunx系统,其中的中文乱码。
常规解决办法
1. 查看文本文件的编码
[root@localhost example]# file -i 7-2.c
7-2.c: text/x-c; charset=iso-8859-1
2. 利用iconv命令进行转码
[root@localhost example]# iconv -f iso-8859-1 -t utf-8 7-2.c
#include <stdio.h>
/*
ÀûÓÃÊý×é¼ÆËãì³²¨ÄÇÆõÊýÁеÄÇ°10¸öÊý
¼´ 1,1,2,3,5,...,55 ²¢°´ÕÕÿÐÐ5¸öÊýµÄ¸ñʽÊä³ö
*/
int main()
{
int list[10] = {1,1};
int i;
for(i=2; i<10; i++) {
list[i] = list[i-1] + list[i-2];
}
for(i=0; i<10; i++) {
printf("%d\t", list[i]);
if ((i+1)%5 == 0) {
printf("\n");
}
}
return 0;
}
可见,仍然是乱码!!!
这里边的坑
file命令识别文件的编码不正确
我这个文件的正确编码应该是GBK
[root@localhost example]# iconv -f GBK -t utf-8 7-2.c
#include <stdio.h>
/*
利用数组计算斐波那契数列的前10个数
即 1,1,2,3,5,...,55 并按照每行5个数的格式输出
*/
int main()
{
int list[10] = {1,1};
int i;
for(i=2; i<10; i++) {
list[i] = list[i-1] + list[i-2];
}
for(i=0; i<10; i++) {
printf("%d\t", list[i]);
if ((i+1)%5 == 0) {
printf("\n");
}
}
return 0;
}
两个问题
有没有能够准确识别文件编码的工具?如果没有,能不能自己写一个?
批量转码脚本
# 设置调试参数 │[root@localhost data]# ls
set -ueEo pipefail; │7-2.c 7-3.c 7-4.c 7-5.c 7-6.c
#读取参数 │[root@localhost data]# bash mutil-iconv.sh -f gbk -t utf-8 data/*.c
while getopts ":f:t:" OPT; do │bash: mutil-iconv.sh: No such file or directory
case "$OPT" in │[root@localhost data]# cd ..
f) │[root@localhost script]# bash mutil-iconv.sh -f gbk -t utf-8 data/*.c
from_code=$OPTARG; │data/7-2.c data/7-3.c data/7-4.c data/7-5.c data/7-6.c
;; │/usr/bin/iconv: illegal input sequence at position 53
t) │/usr/bin/iconv: illegal input sequence at position 40
to_code=$OPTARG; │/usr/bin/iconv: illegal input sequence at position 34
;; │/usr/bin/iconv: illegal input sequence at position 39
?) │/usr/bin/iconv: illegal input sequence at position 39
echo "arg err" >&2; │[root@localhost script]# bash mutil-iconv.sh -f gbk -t utf-8 data/*.c
exit 1; │data/7-2.c data/7-3.c data/7-4.c data/7-5.c data/7-6.c
;; │/usr/bin/iconv: illegal input sequence at position 39
esac │[root@localhost script]#
done │
# 检查必要的参数 │
if [ -z "$from_code" ]; then │
echo "必须传入源文件的编码" >&2; │
exit 1; │
fi │
if [ -z "$to_code" ]; then │
echo "必须传入要转换的编码" >&2; │
exit 1; │
fi │
# 读取文件列表 │
shift $((OPTIND-1)); │
# 读入数组中 │
file_list=($@); │
# 循环处理 │
for item in ${file_list[*]} │
do │
#echo /usr/bin/iconv -f "$from_code" -t "$to_code" -o "$item" "$item"; │
/usr/bin/iconv -f "$from_code" -t "$to_code" -o "$item" "$item"; │
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。如下:
[root@localhost script]# getopts "hf:" OPT -h │
[root@localhost script]# echo $OPT │
h │
[root@localhost script]# getopts "hf:" OPT aa bb │
[root@localhost script]# echo $OPT │
? │
[root@localhost script]#
一种调试方式
#echo /usr/bin/iconv -f "$from_code" -t "$to_code" -o "$item" "$item";
# 可以打印命令最终执行的样子