Note
  • Introduction
  • JS
    • JS / JQuery 代码、框架收藏
    • 用Mock.js + AngularJS来提高开发效率
    • 在JavaScript中监听 IME 键盘输入事件
    • 如何组织大型JavaScript应用中的代码?
    • 深入理解javascript原型和闭包
      • 1. 一切都是对象
      • 2. 函数和对象的关系
      • 3. prototype原型
      • 4. 隐式原型
      • 5. instanceof
      • 6. 继承
      • 7. 原型的灵活性
      • 8. 简述【执行上下文】上
      • 9. 简述【执行上下文】下
      • 10. this
      • 11. 执行上下文栈
      • 12. 简介【作用域】
      • 13. 【作用域】和【上下文环境】
      • 14. 从【自由变量】到【作用域链】
      • 15. 闭包
      • 16. 补充:上下文环境和作用域的关系
    • AngularJS
      • AngularJS开发一些经验总结
      • AngularJS Controller 间通信机制
      • AngularJS 中的一些坑
      • 如何解决AngularJs在IE下取数据总是缓存的问题
      • AngularJS之$timeout指令
      • angular 代码日记
      • AngularJS Directive 隔离 Scope 数据交互
      • 在Angular指令中使用NgModelController做数据绑定
      • AngularJS的ngTransclude
      • 使用Angularjs的ng-cloak指令避免页面乱码
      • Directive - Compile vs. Link
    • NodeJS
      • npm的配置管理及设置代理
    • Angular
      • Angular2 - Control Validation on blur
      • Angular2 - how to call component function from outside the app
  • Go
    • How to Test Local Changes with Go Mod
  • Java
    • Java中根据字体得到字符串高度和长度
    • JAVA 判断一个字符串是不是一个合法的日期格式
    • JVM上的随机数与熵池策略
    • tomcat7+jdk的keytool生成证书 配置https
    • Spring
      • SpringMVC中用@ParamVariable传递的参数包含斜杠(/)时,匹配不了报404错误的解决方案
      • SpringMVC 中HttpMessageConverter简介和Http请求415 Unsupported Media Type的问题
      • Spring Boot 打包,分离依赖jar,配置文件
      • SpringBoot启动后 Stopping service [Tomcat]
      • spring-boot打包时排除第三方依赖
    • 第一个Eclipse插件
    • Eclipse 使用技巧
    • HighChart利用servlet导出中文PNG图片乱码问题解决
    • JDK中文字体在Linux操作系统的设置方案
    • Shiro
      • Shiro-Authentication(身份验证)
      • Shiro-Authorization(授权)
    • 详谈再论JAVA获取本机IP地址
  • Python
    • pip国内镜像源的配置
  • Linux
    • Shell脚本 bad interpreter:No such file or directory & /bin/bash^M: bad interpreter错误解决方法
    • 10个重要的Linux ps命令实战
    • Linux 下执行定时任务 crontab 命令详解
    • CentOS 7.x设置自定义开机启动,添加自定义系统服务
    • CentOS 7 下使用 Firewall
    • 在Ubuntu 12.04安装和设置SSH服务
    • 配置CENTOS YUM更新源
    • Linux下终端利器tmux
    • scp命令
    • Linux系统管理常用命令
    • 让你提升命令行效率的 Bash 快捷键 [完整版]
    • SELinux
    • Linux下 RabbitMQ的安装与配置
    • SELinux下更改mysql端口
    • centos 7 升级后yum install出现Exiting on user cancel
    • Linux Shell 通配符、元字符、转义符使用实例介绍
  • Other
    • Docker
      • Docker Proxy
    • Swagger
      • Spring MVC 集成 Swagger
    • Maven
      • maven plugin的execution出错
      • nexus repair或update index 没反应 速度慢 手动配置nexus index
      • nexus 搭建 maven 私服
      • Maven类包冲突终极解决小技若干
      • org.codehaus.plexus.archiver.jar.Manifest.merge(org.codehaus.plexus.archiver.jar.Manifest)
      • Maven 生命周期
      • wagon-maven-plugin
      • Maven中-DskipTests和-Dmaven.test.skip=true的区别
    • MySQL
      • is not allowed to connect to this MySQL server 解决办法
      • MySQL备份--mysql dump
      • MySQL启动中 InnoDB: Error: log file ./ib_logfile0 is of different size 0 5242880 bytes 的问题
      • MySQL修改root密码的多种方法
      • MySQL长事务导致的Table Metadata Lock
      • com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure
      • 解决mysql插入数据时出现Incorrect string value: '\xF0\x9F...' for column 'name' at row 1的异常
    • HTTP
      • HTTP 协议中的 Transfer-Encoding
      • 四种常见的 POST 提交数据方式
      • HTTP 请求头中的 X-Forwarded-For
      • 传统轮询、长轮询、服务器发送事件与WebSocket
    • Raspberry
      • 系统安装配置
    • VIM
      • vim常用配置
      • 在vim中使用查找命令查找指定字符串
      • Vim缩进有关的设置总结
    • Git
      • github 同步一个 fork
      • Git 如何 clone 非 master 分支的代码
      • git提示error setting certificate verify locations解决办法
      • git设置和取消代理
      • How to Delete Commit History in Github
      • Windows下使用Beyond Compare作为git的比对与合并工具
    • 解决 Virtualbox 共享文件夹 cannot create symlink error 问题
    • nginx 403 forbidden 二种原因
    • VirtualBox的四种网络连接方式
    • 在Windows的CMD中如何设置支持UTF8编码?
    • nginx使用ssl模块配置HTTPS支持
    • 怎么查看WINDOWS端口被哪个程序占用
    • VMWare 随系统启动指定虚拟机
    • 使用命令行启动VirtualBox虚拟机
    • 该死的^M
    • install home-assistant mosquitto-broker and node-red on android
    • SSH原理与运用:远程登录、远程操作与端口转发
    • SVN mime-type 笔记
    • VirtualBox虚拟机网络配置(NAT + Host-only - Bridged)
    • VirtualBox绿色版的桥接网卡驱动安装
    • OAuth的改变
    • MavenActionUtil.getMavenProject(e.getDataContext()) is Null when developing a intellij plugin
    • Cygwin的安装和配置apt-cyg源
    • Zookeeper运维常用四字命令
    • svn sqlite[S11]: database disk image is malformed
Powered by GitBook
On this page
  • ^M 是何方神圣
  • ^M 会导致什么样的问题?
  • 如何逃离 ^M 的魔掌
  • 一、临时解决的几个方法
  • 二、预防此问题
  • 三、防止被别人坑

Was this helpful?

  1. Other

该死的^M

^M,神奇的字符!相信很多人写 Shell 脚本的时候都被这个字符坑过,我自己也至少被坑过两次。最近周围的好几个小伙伴又被 ^M 坑,花了好几个小时检查脚本的错误,结果发现是 ^M 导致的。所以写了这篇文章讲一下什么是 ^M,当 ^M 出现的时候一般会伴随着什么样的现象,出现了我们可以用什么手段去解决。

^M 是何方神圣

这个得先从 Windows 和 Unix 下的换行符开始说起,在我的 Intellij IDEA 的右下方的状态栏上,有一块是展示当前文件的换行符的: 可以看到在 Windows 下,换行符是 \r,在 Unix 下换行符是 。如果我们用把一个文件的换行符换成 Windows 的换行符,那么当我们用 cat -v 来看的时候,就可以看到: 实际上 ^M 就是 Windows 下的换行符中的 部分。因为 Unix 下的换行符是 ,所以当一个用 Windows 下的换行符的文件放在 Unix 下的时候,单行的最后一个字符就变成了 , 在 ASCII 码中是 0xD,而 0xD 在 VIM 和 cat -v 则刚好被显示为 ^M。

刚才之所以用 cat -v 而不用普通的 cat 是因为 ^M 是不可见的字符,如果仅仅用 cat,是看不到这个字符的。cat 的 -v 参数的作用就是显示不可打印的字符。

^M 会导致什么样的问题?

我们已经知道了 ^M 实际上就是 ,而 是回车符(Carriage Return),回车符的作用是将设备的位置重置到当前行的开头。

知道了 的作用时候,我们来看一个现象:

### 有一个普通文件,存放了一个路径,当前行的最后以 ^M 结尾
$ cat -v Main
/home/admin/khotyn.huangt/test/^M

### Echo 一下,神奇了!
$ echo "`cat Main`/where am i"
/where am i/khotyn.huangt/test/

看到后面那个 echo 命令,它将 Main 文件中的内容提取出来,再在后面加上 /where am i 这个字符串,结果我们看到,/where am i 在打印的结果中跑到最前面去了,这正是 这个字符的作用,因为 cat Main 的执行的结果的最后一个字符是 ,所以一遇到这个字符,设备指针就直接回到了当前行的开头,所以 后面的 /where am i 就直接显示在了最前面。

所以,当你看到什么奇怪的路径,这个路径中莫名其妙地少了一些字符,出现了一些莫名其妙的字符串的,很可能就是 ^M 导致的。

如何逃离 ^M 的魔掌

当你发现了 ^M 导致的问题的时候,最直截了当的方式就是将 ^M 从文件中去掉。

一、临时解决的几个方法

如果的机器上安装有 dos2unix,那么恭喜你,直接运行

dos2unix /path/to/file

就可以将一个文件的换行符从 Windows 的转换成 Unix 的。

但是,如果机器上没有装 dos2unix,而你又没法装上去(在一家公司工作总是会有各种各样的让你感觉很丧气的权限控制),那么你可以用 sed 来替换:

sed --in-place='' 's/^M//g' /path/to/file

注意:上面的 ^M 只是显示的效果,输入的时候需要用组合键输入,先 Ctrl + V,然后马上 Ctrl + M 就可以在终端中输入 ^M 了。

当然,用 tr 之类的命令也可以,不过我一般用 sed 的原因是 sed 加上 --in-place 参数可以做到直接替换原文件,而不用产生临时的文件(危险而高效的操作)。

二、预防此问题

不过,前面说的只是当出现问题的时候如何解决,那么如何预防这个问题呢?

第一个方法当然是直接放大招,换个 Mac 啥的,或者把你的机器上的 Windows 格了,装个 Ubuntu 也好啊。真心觉得 Windows 对于程序员来说真的没有啥好处(我好想听说连微软都开源 .Net 了,并且会提供多平台的支持)。

第二个方法嘛,当在 Windows 下使用各种编辑器的时候,尽量将换行符设置成 Unix 的换行符。不要偷懒用 Windows 的换行符,出现了问题就是好几个小时的排查时间。(目前没有发现有什么场景下有必须用到 Windows 下的换行符的,如果有同学知道有这样的场景的话,不吝赐教)。

三、防止被别人坑

Previous使用命令行启动VirtualBox虚拟机Nextinstall home-assistant mosquitto-broker and node-red on android

Last updated 5 years ago

Was this helpful?

虽然我个人觉得不应该用 Windows,不过还是有同学的确是喜欢用,或者因为不可抗拒的因素而暂时在使用,为了防止出现这个问题,可以在版本管理软件上做控制,比如 Git 就可以设置换行符,当你提交文件的时候,可以将你的所有文本的换行符替换成你设定的换行符,详细可以看

https://help.github.com/articles/dealing-with-line-endings/