Linux 替换^M字符方法

来源:互联网 发布:健身理论 知乎 编辑:程序博客网 时间:2024/05/19 03:24

  最近遇到一个通过windows上传文本数据到linux服务器,但是读取数据文件时,因为每行数据后面出现^M字符,导致通过程序读取数据失败,希望把^M字符替换成换行字符,所以对这一块仔细研究了下。网上的方法很多,也很杂,有很多网友都说通过dos2unix就可以搞定,其实在有些情况下,这个命令是行不通的,具体原因待会再说,下面讲述一个通过linux命令处理的通用方法(为什么强调linux命令?因为待会我会给出一个通过程序处理的方法):

$ sed -i 's/^M/\n/g' myfile.txt//注意:这里的“^M”要使用“CTRL-V CTRL-M”生成,而不是直接键入“^M”

  强调一下,命令中的^M不是直接输入^和M哈,是在linux中敲“CTRL-V CTRL-M”生成的,这个需要注意,因为在linux下^M其实是一个字符,你如果直接敲^和M,那就是2个字符了,然后意义也完全不一样。
  可能你会问,我可以通过dos2unix命令搞定啊:

$ dos2unix myfile.txt

  是的,这种方式的确可以解决大部分问题,但有时也解决不了,为什么?这个需要讲述windows、linux和OS换行符的不同标准,不过在讲该标准前,需要明确几个概念:
  回车:用“\r”表示,ASCII码中的“代码”为CR,意义是将光标移到当前行的首位;
  换行:用“\n”表示,ASCII码中的“代码”为LF,意义是将光标移到下一行。
  ASCII码可以参考下图:
  这里写图片描述
  
  下面直接上干货,windows、linux、mac系统的换行符:
  (1) DOS/Windows系统采用CRLF(回车+换行)表示下一行,即“\r\n”;
  (2) Linux/UNIX系统采用LF表示下一行,即“\n”;
  (3) MAC系统采用CR表示下一行,即“\r”;
  可能你会问,我怎么知道我的文本数据结尾是哪种,有没有什么工具可以显示出来?当然可以,用Notepad++,点击菜单中Edit->EOL Conversion,会展开Windows Format、UNIX/OSX Format、Old Mac Format这3中转换格式,具体意义通过名字很简单理解,下面让我们看看这3中格式的数据在Notepad++中是如何显示的,原数据和通过3种方式显示如下:
  
这里写图片描述 这里写图片描述 这里写图片描述 这里写图片描述

  可能你会问,不就一个换行,怎么搞的这么复杂,感兴趣的同学可以参考文章《DOS、Mac 和 Unix 文件格式 》,你就知道它们的起源了。
  还是回到最开始我们讨论的问题,为什么linux数据出现^M,用命令dos2unix有时行不通,如果你的数据结尾是CRLF,即windows类的数据,这个当然没有问题,但如果结尾是CR,用dos2unix就行不通了,因为dos2unix命令用来将DOS/Windows格式的文本文件转换成UNIX格式的,CR是Mac格式,那怎样将Mac格式数据转成Linux呢?用命令mac2unix即可:

$ mac2unix myfile.txt

  如果想逆转,也有对应的命令unix2dos、unix2mac,是不是很简单呢,哈哈~~
  上面讲述的是“不同系统换行符基本原理”和“通用linux解决^M问题”,其实很多时候我们需要通过程序来处理,例如通过windows或Mac文件上传到linux服务器,然后在linux服务器上通过程序读取文件,这时就会遇到换行符问题,那么怎样通过程序来解决呢?下面是通过PHP语言,然后结合AWK方式处理:

$fileFullName = './myfile.txt';$tmpFile = './temp.txt';$cmd = "cat {$fileFullName}|awk -F\"[\r\n]\" '{for(i=1;i<=NF;i++)if(\$i!~/^$/)print \$i}' > {$tmpFile};mv {$tmpFile} {$fileFullName}";shell_exec($cmd);

  可能大家对AWK不熟,我解释一下吧,前两行是定义文件(最好写全路径,我这里只是演示),第三行是通过awk处理文件的命令:将文件fileFullName每行按照分隔符“\r”和“\n”进行分割,分割后的数据,通过“i!~/^$/”判断非空,然后将非空的数据导入tmpFile,数据全部处理完后,用tmpFile文件覆盖fileFullName文件。

0 0
原创粉丝点击