我在《Linux环境打开Windows下编写的中文文档乱码问题》一文是提到在linux环境下用可以用mousepad或leafpad文本阅读器打开windows下文本解决中文乱码。博友inbi在评论中说有”有unix2dos和dos2unix这两个命令“。首先,我在上一博文中要解决的问题是在LINUX环境下正常阅读Windows下编写的含有中文字符的文本,而不对文本进行写操作(即改变文本格式:比如格式转换、属性、权限等操作),在这里,我也提醒各位做LINUX系统管理的朋友,在LINUX系统环境下,在对任何文件进行写操作时都尽量保持审慎态度(比如一个业务数据文件的Modify属性的改变就有可能导致基于此属性的数据备份任务失败)。其次,unix2dos和dos2unix这两个命令是用来转换文本断行格式的,而无法对文本的字符编码进行转换。下面,我就linux下文本字符编码转换和断行字符转换给大家讲解。
接下来,我们依旧使用《Linux环境打开Windows下编写的中文文档乱码问题》一文中的afaty@afaty-laptop ~/Downloads/system_status/Readme.txt进行演示。
我们先看一下,这个文件还是原来那个文档
afaty@afaty-laptop ~/Downloads/system_status $ cat Readme.txt # 没错,还是那个文件,依旧乱码。 ����ʹ� ��������ѹ������Ҫ�������κ�UNIX/Linuxϵͳ��,Ȼ��ִ�����еĽű��ļ���� #./cpu.sh disk.sh��ʹ����Ҫ��������,��/dev/sda1� ��һ����ҪrootȨ� Ŀǰ֧�ֵ�ϵͳƽ̨:Linux,AIX,Solaris,HP-UX,SCO-UNIX
一、文本字符编码转换
第一种方法:使用enca命令进行转换。
这个工具一般LINUX发行版默认没有安装,如果你要使用需要手动安装。
afaty@afaty-laptop ~/Downloads/system_status $ file -bi Readme.txt #我们先看一下这个文本的编码格式。 text/plain; charset=iso-8859-1 # file命令太笨了,竟然猜错了……不可能是iso-8859-1的,我们试试别的工具。 afaty@afaty-laptop ~/Downloads/system_status $ enca -L zh_CN Readme.txt # enca这个工具还是聪明些。不过我们还是需要给它指定语言(zh_CN)。 Simplified Chinese National Standard; GB2312 afaty@afaty-laptop ~/Downloads/system_status $ cp Readme.txt Readme.txt.GB2312 # 我们先拷贝一份文件用来实验。 afaty@afaty-laptop ~/Downloads/system_status $ enca -L zh_CN -x UTF-8 Readme.txt.GB2312 # 转化为UTF-8格式,这里在原文件上直接转化了。 afaty@afaty-laptop ~/Downloads/system_status $ cat Readme.txt.GB2312 # 中文正常显示了。除了enca,我们还可以用iconv这个命令来实现,下面看我实验。 如何使用 将程序解压到你需要监测的任何UNIX/Linux系统中,然后执行其中的脚本文件即可 #./cpu.sh disk.sh的使用需要给出参数,如/dev/sda1等 不一定需要root权限 目前支持的系统平台:Linux,AIX,Solaris,HP-UX,SCO-UNIX # 为了不改变原文件,我们可以用以下方式转换。 afaty@afaty-laptop ~/Downloads/system_status $ rm -rf Readme.txt.GB2312 afaty@afaty-laptop ~/Downloads/system_status $ cp Readme.txt Readme.txt.GB2312 afaty@afaty-laptop ~/Downloads/system_status $ enca -L zh_CN -x UTF-8 < Readme.txt.GB2312 > Readme.txt.UTF-8 存入Readme.txt.UTF-8文件中。 afaty@afaty-laptop ~/Downloads/system_status $ cat Readme.txt.UTF-8 如何使用 将程序解压到你需要监测的任何UNIX/Linux系统中,然后执行其中的脚本文件即可 #./cpu.sh disk.sh的使用需要给出参数,如/dev/sda1等 不一定需要root权限 目前支持的系统平台:Linux,AIX,Solaris,HP-UX,SCO-UNIX
第二种方法:使用iconv命令进行转换。
这个工具一般LINUX发行版默认已经安装,可以直接使用。
afaty@afaty-laptop ~/Downloads/system_status $ rm -rf Readme.txt.GB2312 afaty@afaty-laptop ~/Downloads/system_status $ rm -rf Readme.txt.UTF-8 afaty@afaty-laptop ~/Downloads/system_status $ cp Readme.txt Readme.txt.GB2312 afaty@afaty-laptop ~/Downloads/system_status $ iconv -f GB2312 -t UTF-8 < Readme.txt.GB2312 如何使用 将程序解压到你需要监测的任何UNIX/Linux系统中,然后执行其中的脚本文件即可 #./cpu.sh disk.sh的使用需要给出参数,如/dev/sda1等 不一定需要root权限 目前支持的系统平台:Linux,AIX,Solaris,HP-UX,SCO-UN afaty@afaty-laptop ~/Downloads/system_status $ iconv -f GB2312 -t UTF-8 < Readme.txt.GB2312 > Readme.txt.UTF8 #保存到Readme.txt.UTF8文件中。 afaty@afaty-laptop ~/Downloads/system_status $ cat Readme.txt.UTF-8 如何使用 将程序解压到你需要监测的任何UNIX/Linux系统中,然后执行其中的脚本文件即可 #./cpu.sh disk.sh的使用需要给出参数,如/dev/sda1等 不一定需要root权限 目前支持的系统平台:Linux,AIX,Solaris,HP-UX,SCO-UNIX
二、文本断行字符转换
这里我们主要讨论如何将Windows下编写的脚本的断行格式转化为LINUX下脚本断行格式。我们在现在项目中经常遇到,我们的程序写的没有任何问题,但就是无法正常执行,一般都是因为不同操作系统平台下编写程序而导致程序中的断行格式不同造成的。下面我们看一个实例。我用bash在windows和linux下分别编写了一个Hello,World程序,程序中写了一样的东西。程序名分别为hello-win.sh和hello-linux.sh。下面我们用diff工具看一下。
afaty@afaty-laptop /tmp $ diff hello-win.sh hello-linux.sh 1,5c1,5 < #!/bin/bash < # filename: hello-win.sh < # It is my first bash script. < < echo "Hello, World!" --- > #!/bin/bash > # filename: hello-linx.sh > # It is my first bash script. > > echo "Hello, World."
从上面的代码中好像看不出来什么哦,但问题却是实实在在的,估计多数码农都是被类似问题弄疯的。下面我们尝试执行一下这两个脚本看看。
afaty@afaty-laptop /tmp $ chmod +x hello-win.sh hello-linux.sh # 先给两个程序加执行权限。 afaty@afaty-laptop /tmp $ ./hello-win.sh bash: ./hello-win.sh: /bin/bash^M: bad interpreter: No such file or directory afaty@afaty-laptop /tmp $ ./hello-linux.sh Hello, World. afaty@afaty-laptop /tmp $
我们可以看到,上面两个脚本执行的结果:hello-win.sh执行错误,hello-linux.sh没问题。那我们用别的工具看看,看两个文件到底有什么不一样。
afaty@afaty-laptop /tmp $ cat -A hello-win.sh hello-linux.sh #!/bin/bash^M$ # filename: hello-win.sh^M$ # It is my first bash script.^M$ ^M$ echo "Hello, World!"^M$ #!/bin/bash$ # filename: hello-linx.sh$ # It is my first bash script.$ $ echo "Hello, World."$
从以上代码中我们可以看到,hello-win.sh文件中的换行符为“^M$”,而hello-linux.sh文件中的换行符是”$”。问题就在这里了。现在,我们用inbi兄提到的dos2unix命令转换一下hello-win.sh文件中的换行符看看。
第一种方法:使用dos2unix
afaty@afaty-laptop /tmp $ cp hello-win.sh hello-win.sh.orig afaty@afaty-laptop /tmp $ dos2unix hello-win.sh dos2unix: converting file hello-win.sh to UNIX format ... afaty@afaty-laptop /tmp $ cat -A hello-win.sh #!/bin/bash$ # filename: hello-win.sh$ # It is my first bash script.$ $ echo "Hello, World!"$ afaty@afaty-laptop /tmp $ ./hello-win.sh Hello, World!
第二种方法:使用sed命令
我们看到,hello-win.sh和hello-linux.sh两个文件的区别主要在于hello-win.sh的换行符多了个“^M”,那么从理论上来讲,我们只要把“^M”控制字符删掉即可。下面我们实验验证。
afaty@afaty-laptop /tmp $ cp hello-win.sh.orig hello-win.sh afaty@afaty-laptop /tmp $ cat -A hello-win.sh #!/bin/bash^M$ # filename: hello-win.sh^M$ # It is my first bash script.^M$ ^M$ echo "Hello, World!"^M$ afaty@afaty-laptop /tmp $ sed -i 's/^M//g' hello-win.sh afaty@afaty-laptop /tmp $ cat -A hello-win.sh #!/bin/bash$ # filename: hello-win.sh$ # It is my first bash script.$ $ echo "Hello, World!"$ afaty@afaty-laptop /tmp $ chmod +x hello-win.sh afaty@afaty-laptop /tmp $ ./hello-win.sh Hello, World!