在跨平台开发或文件传输过程中,经常遇到文本文件换行符不一致的问题。Windows系统默认使用回车符+换行符(CRLF,即\r\n)作为行结束标志,而Linux/Unix系统则只使用换行符(LF,即\n)。这种差异可能导致脚本执行失败、配置文件解析错误、版本控制系统显示大量无意义差异等困扰。本文将详细介绍换行符的概念、如何查看文件换行符格式,以及多种转换方法,帮助你在Linux环境下轻松处理CRLF与LF的转换问题。

博主博客

一、换行符概念

换行符是文本文件中用于标记一行结束并开始新一行的控制字符。不同操作系统采用了不同的约定:

  • CRLF(Carriage Return + Line Feed):由两个字符组成——回车符(\r,ASCII 13)和换行符(\n,ASCII 10)。常见于Windows和DOS系统。
  • LF(Line Feed):仅由换行符(\n,ASCII 10)表示。Unix、Linux以及现代macOS(macOS以前使用CR,即\r)都使用LF。

当Windows格式的文本文件(CRLF)在Linux下打开时,可能会在行尾出现^M字符,或者在处理时出现意外错误。反之,Linux格式的文件在Windows记事本中打开时,所有内容会挤在一行,难以阅读。因此,掌握换行符转换技巧十分必要。

二、查看文件换行符格式

在处理文件之前,先确认其当前的换行符格式。Linux提供了多种查看方式。

1. 使用 file 命令

file 命令可以识别文件类型,并显示换行符信息。

file nukix.sh

输出示例:

nukix.sh: Bourne-Again shell script, ASCII text executable, with CRLF line terminators

从输出可以看到该文件使用了CRLF换行符。

2. 使用 cat -v 命令

cat -v 会将不可见字符以脱字符(caret notation)显示,其中CR(回车符)会显示为 ^M

cat -v nukix.sh

如果每行末尾都出现 ^M,说明是CRLF格式。

3. 使用 odhexdump 查看十六进制

通过查看文件原始字节,可以明确看出换行符的十六进制值(CR=0d,LF=0a)。

od -c nukix.sh | head
# 或
hexdump -C nukix.sh | head

od -c 输出中,CRLF会显示为 \r \n

4. 使用 sedgrep 探测

# 检查文件是否包含CRLF(即回车符)
grep -U $'\r$' nukix.sh

若存在匹配,则文件包含CRLF。

三、使用 dos2unix / unix2dos 进行转换

dos2unixunix2dos 是专门用于转换换行符的命令行工具,功能强大且易于使用。

安装

在Debian/Ubuntu系统上:

sudo apt update
sudo apt install dos2unix -y

在Red Hat/CentOS上:

sudo yum install dos2unix

基本用法

  • dos2unix:将CRLF转换为LF(DOS → Unix)
  • unix2dos:将LF转换为CRLF(Unix → DOS)

1. 转换单个文件

直接在源文件上修改(默认行为):

dos2unix file.txt

转换后 file.txt 将变为LF格式。

2. 保留原始文件,输出到新文件

使用 -n 参数(-n 表示新文件):

dos2unix -n oldfile.txt newfile.txt

3. 同时转换多个文件

dos2unix file1.txt file2.txt file3.txt

或者明确使用 -o(覆盖源文件):

dos2unix -o file1.txt file2.txt

4. 保持文件时间戳不变

使用 -k 选项,转换后文件的修改时间保持不变:

dos2unix -k file.txt

5. 批量转换当前目录下的所有文件

结合 find 命令:

find . -type f -name "*.txt" -exec dos2unix {} \;

或者通过管道:

find . -type f | xargs dos2unix

常用选项总结

选项 作用
-k 保持文件时间戳
-q 安静模式,不显示警告
-n 转换到新文件,保留源文件
-c 指定转换模式(ASCII, 7bit, ISO, Mac 等)

四、其他转换方法

除了专用工具,Linux下还有许多经典命令可以完成换行符转换,适合在脚本中灵活使用。

1. 使用 sed

  • CRLF → LF:删除所有回车符

    sed -i 's/\r$//' file.txt
    

    -i 直接修改文件;若不加 -i,则输出到标准输出。

  • LF → CRLF:在每行末尾添加回车符

    sed -i 's/$/\r/' file.txt
    

2. 使用 tr

tr 命令可以删除或替换字符。

  • CRLF → LF:删除所有回车符
    tr -d '\r' < input.txt > output.txt
    
  • LF → CRLF:将换行符替换为回车+换行(注意:需要将换行符视为分隔符处理,比较复杂,一般用 sedunix2dos 更方便)

3. 使用 awk

# CRLF → LF
awk '{ sub(/\r$/, ""); print }' input.txt > output.txt

# LF → CRLF
awk '{ printf "%s\r\n", $0 }' input.txt > output.txt

4. 使用 Vim 编辑器

在Vim中打开文件,执行以下命令:

  • 转换为LF(Unix格式): :set fileformat=unix 然后 :wq
  • 转换为CRLF(DOS格式): :set fileformat=dos 然后 :wq
  • 转换为CR(Mac格式): :set fileformat=mac

5. 使用 perl

# CRLF → LF
perl -pe 's/\r$//' input.txt > output.txt

# LF → CRLF
perl -pe 's/$/\r/' input.txt > output.txt

6. 使用 python

# CRLF → LF
python -c "import sys; sys.stdout.write(open(sys.argv[1]).read().replace('\r\n', '\n'))" input.txt > output.txt

五、总结

场景 推荐方法
快速查看文件格式 filecat -v
单个文件转换(保留原文件) dos2unix -n old newsed
批量转换目录下所有文件 find ... -exec dos2unix {} \;
脚本中自动转换 sed -i 's/\r$//'tr -d '\r'
需要保留时间戳 dos2unix -k

处理换行符问题不仅能避免脚本执行异常,还能让代码在跨平台协作时保持整洁。掌握上述工具和方法,可以让你在面对任何换行符难题时游刃有余。

参考文献