详解Shell脚本中^M的问题和解决方案

目录
  • ^M 是什么?
  • 本质原因
  • 常用工具

在开发过程中,有时候不小心将Windows本地创建的shell脚本(以 .sh 结尾的脚本),传到linux系统中,通过 vi或者view命令查看文件时,发现在末尾发现出现了很多^M字符。

^M 是什么?

这个字符就是换行符。是由于跨平台解析的原因。
因为window和Linux下对行尾的换行的定义不同
Windows: \r\n
Linux/Unix: \n
Mac: \r

例子

出现的原因:
在DOS/Windows里,文本文件的换行符为\r\n,而在nix系统里则为\n,所以DOS/Windows里编辑过的文本文件到了nix里,每一行都多了个^M

导致的问题:
脚本可能无法正常执行,影响程序正常使用

临时解决方案1:

如果需要从表面上修改,只需使用替换命令就能将该字符给取消;#:%s/^M//g

临时解决方案2:

在linux上创建一个文件,名称为 xxx.sh,将这个问价下载到本地,然后将脚本内容粘贴进去,重新上传到linux上打开查看。

补:解决方法

如果需要转换,我们只需要转换文件格式即可。你可以选择直接在服务器上调整。包括如下三种方式。
(1)使用linux命令dos2unix filename,直接把文件转换为unix格式
(2)使用sed命令sed -i "s/\r//" filename  或者 sed -i "s/^M//" filename直接替换结尾符为unix格式
(3)vi filename打开文件,执行 : set ff=unix 设置文件为unix,然后执行:wq,保存成unix格式。

本质原因

跨平台造成的编码格式问题。其实这个是历史遗留问题,根本原因就是对换行符的内存组成问题。在unix操作系统下的换行符格式为0A(ascii码),而dos格式下的换行符为 0D 0A(也就是),其实就显示为^M了。并且对于这个原因,也是有历史的。
unix将换行符的字符形式给转变了,然而,dos命令下任然保留着传统的表达方式;所以以后在进行跨平台开发的时候,前提就是考虑是否兼容,是否编码格式兼容这些基本的前提条件。

历史来源:
早期的计算机输出设备不是显示器,而是电传打字机,结构与普通的打字机差不多。有一个打印头在纸上打字,同时有一个电动机控制纸张的进出。当打印头到达行尾的时候,需要两个动作才能够到达下一行的行首:首先执行回车动作,将打印头移动到本行的行首,然后进行换行动作,电动机将纸张向上移动一行,这样打印头就处于下一行的行首,可以继续进行打印。回车和换行对应的控制字符分别是\r和\n,这就是windows中换行符为\r\n的由来。后来由于经常连续执行,所以在打印机中将这两个控制字符简化为一个控制字符,这就是Linux/Unix中的换行符\n的由来。

常用工具

dos2unix 将window下文本文件转成符合Linux系统要求的文件
unix2dos  与上面的命令的作用相反

到此这篇关于详解Shell脚本中^M的问题和解决方案的文章就介绍到这了,更多相关Shell ^M问题内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Shell脚本bash: ./t.sh:/bin/bash^M:损坏的解释器: 没有那个文件或目录

    有时候编写脚本时会出现类似标题列出的错误,这个问题大多数是因为你的脚本文件在windows下编辑过.windows下,每一行的结尾是\n\r,而在linux下文件的结尾是\n,那么你在windows下编辑过的文件在linux下打开看的时候每一行的结尾就会多出来一个字符\r,用cat -A urfile时你可以看到这个\r字符被显示为^M,这时候只需要删除这个字符就可以了.可以使用命令sed -i 's/\r$//' urfile .有时候编写脚本时会出现类似标题列出的错误,这个问题大多数是因为你

  • 详解Shell脚本中^M的问题和解决方案

    目录 ^M 是什么? 本质原因 常用工具 在开发过程中,有时候不小心将Windows本地创建的shell脚本(以 .sh 结尾的脚本),传到linux系统中,通过 vi或者view命令查看文件时,发现在末尾发现出现了很多^M字符. ^M 是什么? 这个字符就是换行符.是由于跨平台解析的原因.因为window和Linux下对行尾的换行的定义不同Windows: \r\nLinux/Unix: \nMac: \r 例子 出现的原因:在DOS/Windows里,文本文件的换行符为\r\n,而在nix系

  • 详解shell脚本中的case条件语句介绍和使用案例

    #前言:这篇我们接着写shell的另外一个条件语句case,上篇讲解了if条件语句.case条件语句我们常用于实现系统服务启动脚本等场景,case条件语句也相当于if条件语句多分支结构,多个选择,case看起来更规范和易读 #case条件语句的语法格式 case "变量" in 值1) 指令1... ;; 值2) 指令2... ;; *) 指令3... esac #说明:当变量的值等于1时,那么就会相应的执行指令1的相关命令输出,值等于2时就执行指令2的命令,以此类推,如果都不符合的话

  • 详解Shell脚本中调用另一个Shell脚本的三种方式

    主要以下有几种方式: Command Explanation fork 新开一个子 Shell 执行,子 Shell 可以从父 Shell 继承环境变量,但是子 Shell 中的环境变量不会带回给父 Shell. exec 在同一个 Shell 内执行,但是父脚本中 exec 行之后的内容就不会再执行了 source 在同一个 Shell 中执行,在被调用的脚本中声明的变量和环境变量, 都可以在主脚本中进行获取和使用,相当于合并两个脚本在执行. 第一种:fork 特点:会生成子PID而且可重复被

  • 详解Shell 脚本中 “$” 符号的多种用法

    通常情况下,在工作中用的最多的有如下几项: $0:Shell 的命令本身 1到9:表示 Shell 的第几个参数 $? :显示最后命令的执行情况 $#:传递到脚本的参数个数 $$:脚本运行的当前进程 ID 号 $*:以一个单字符串显示所有向脚本传递的参数 $!:后台运行的最后一个进程的 ID 号 $-:显示 Shell 使用的当前选项 ...... 今天将通过以上几种选项并做进一步的操作案例: 1.引用变量 引用变量时,使用 $ 符号直接来进行引用,以及包括循环变量: [root@localho

  • 详解shell脚本[] [[]] -n -z 的含义解析

    在写脚本的时候,总是搞不懂[] [[]]的区别,这次写一个总结,把它掌握牢固 []和test 两者是一样的,在命令行里test expr和[ expr ]的效果相同. test的三个基本作用是判断文件.判断字符串.判断整数.支持使用 "与或非" 将表达式连接起来. test中可用的比较运算符只有==和!=,两者都是用于字符串比较的,不可用于整数比较,整数比较只能使用-eq, -gt这种形式. 无论是字符串比较还是整数比较都千万不要使用大于号小于号.当然,如果你实在想用也是可以的,对于字

  • 详解shell脚本的编写规范

    编写shell脚本的一些规范 解释器 shell脚本一般选择bash作为解释器,脚本开头应为 #!/bin/bash 或 #!/bin/sh 添加脚本版本和注释功能 在脚本的开头加注释,说明脚本作者.编写时间.脚本功能,最好可以加上脚本的版本号.shell中脚本注释用#,注释语句和#号之间有一个空格 #!/bin/bash # 脚本版本 # 脚本作者 # 脚本时间 # 脚本功能 添加脚本调试 通过set命令添加脚本调试,如果报错,脚本直接退出,不继续执行,对于管道错误也可以直接退出 #!/bin

  • 详解Shell脚本控制docker容器启动顺序

    1.遇到的问题 在分布式项目部署的过程中,经常要求服务器重启之后,应用(包括数据库)能够自动恢复使用.虽然使用docker update --restart=always containerid能够让容器自动随docker启动,但是并不能保证是在数据库启动之后启动,如果数据库未启动,那么将导致应用启动失败;网上还有一种解决方法是通过docker-compose容器编排来控制启动顺序,这个博主研究的比较少. 2.解决思路 使用Shell脚本来控制,思路大致如下 探测数据库端口来检验数据库是否启动成

  • Linux 在Shell脚本中使用函数实例详解

    Linux 在Shell脚本中使用函数实例详解 Shell的函数 Shell程序也支持函数.函数能完成一特定的功能,可以重复调用这个函数. 函数格式如下: 函数名() { 函数体 } 函数调用方式: 函数名 参数列表 实例:编写一函数add求两个数的和,这两个数用位置参数传入,最后输出结果. root@ubuntu:/home/study# vi test3 #!/bin/bash add(){ a=$1; b=$2; z=`expr $a + $b`; echo "The sum is $z&

  • Shell脚本中多命令逻辑执行顺序的方法详解

    Linux中可以使用分号";".双and号"&&"和双竖线"||"来连接多个命令.单"&"符号也算命令连接符号,只不过它是将其前面的命令放入后台执行,所以可以变相地实现命令并行执行. 1.分号";" command1 ; command2 命令之间没有逻辑关系.分号连接的命令会按照顺序从前向后依次执行,但分号两端的命令之间没有任何逻辑关系,所有写出来的命令最终都会被执行,即使分号前面

  • 详解shell中脚本参数传递的两种方式

    方式一:$0,$1,$2.. 采用$0,$1,$2..等方式获取脚本命令行传入的参数,值得注意的是,$0获取到的是脚本路径以及脚本名,后面按顺序获取参数,当参数超过10个时(包括10个),需要使用${10},${11}....才能获取到参数,但是一般很少会超过10个参数的情况. 1.1 示例:新建一个test.sh的文件 #!/bin/bash echo "脚本$0" echo "第一个参数$1" echo "第二个参数$2" 在shell中执行

随机推荐