LF和CRLF换行符区别
在文本文件中,换行可以通过几种不同的字符序列来实现,这主要取决于所使用的操作系统或编程环境。以下是三种常见的换行字符序列:
-
LF (Line Feed): 单独的行进给字符,ASCII值为10(十六进制为0x0A)。这个字符将光标移动到下一行的开始位置。在Unix、Linux和Mac OS X(从OS X 10.0起)中,这是换行的标准方式。在源代码中通常表示为
\n
。 -
CR (Carriage Return): 回车字符,ASCII值为13(十六进制为0x0D)。这个字符将光标移动到当前行的开始位置。在早期的打印机和某些旧的计算机系统中,CR被用来将打印头移回到行的起始位置。在源代码中通常表示为
\r
。 -
CRLF (Carriage Return + Line Feed): 这是CR和LF两个字符的组合,首先将光标移回行首,然后将光标移到下一行的开始位置。这是在Windows操作系统中使用的换行标准。在源代码中通常表示为
\r\n
。
下面是这些换行符的总结:
- Unix/Linux/Mac:
\n
(LF) - Windows:
\r\n
(CRLF)
shell脚本因CRLF换行输出问题
在编写跨平台的脚本或处理来自不同操作系统的文本文件时,了解这些换行符的不同是非常重要的
root@Ubuntu18_04_6-1:~# file a.log
a.log: ASCII text
root@Ubuntu18_04_6-1:~# file ai_all_bmc.log
ai_all_bmc.log: ASCII text, with CRLF line terminators
未处理/r/n换行时的脚本问题
- 当有个如下shell脚本:未考虑处理\r转义字符带来的输出问题
#!/bin/bash
hosts=$(cat ai_all_bmc.log )
for i in $hosts
do
echo -e "$i = $(date +"%Y-%m-%d %H:%M:%S")"
done
- 打印出的结果始终无法将i值和日期时间打印同一行,执行结果如下。
第一次优化脚本,还是异常
当写个脚本逐行打印a.log的ip同时附上日期时
#!/bin/bash
#hosts=$(cat a.log)
hosts=$(cat a.log | tr -d "\r" | tr -d "\n")
for i in $hosts
do
echo -e "$i = $(date +"%Y-%m-%d %H:%M:%S") \n"
done
结果执行结果如下:未能正确换行打印。分析原因如下。
但是,从你运行脚本的结果来看,所有输出都在同一行,没有按预期产生换行。这是因为cat在读取
hosts
时去除了所有的换行符(\n
),这导致for
循环中的$hosts
被解释为一个长字符串,其中包含了所有原本分隔的主机名。
第二次优化后脚本:正确使用tr -d 去除\r
(我固执就是想在循环中去tr删除掉/n)
root@Ubuntu18_04_6-1:~/shell-script# cat cpprint.sh
#!/bin/bash
hosts=$(cat ai_all_bmc.log )
for i in $hosts
do
e=&(echo "$i" | tr -d "\r" | tr -d "\n" )
echo -e "$a = $(date +"%Y-%m-%d %H:%M:%S")"
done
root@Ubuntu18_04_6-1:~/shell-script#
执行效果
当然更优的脚本版本:
root@Ubuntu18_04_6-1:~/shell-script# cat cpprint.sh
#!/bin/bash
#hosts=$(cat a.log)
hosts=$(cat ai_all_bmc.log | tr -d "\r")
#hosts=$(cat ai_all_bmc.log )
for i in $hosts
do
# e=&(echo "$i" | tr -d "\r" | tr -d "\n" )
# printf "%s :%s = %s\n" "$i" "$(date +"%Y-%m-%d %H:%M:%S")" "$check_power_status" | tee -a echo.txt
# printf "%s = %s \n" "$i" "$(date +"%Y-%m-%d %H:%M:%S")" | tee -a echo.txt
echo -e "$i = $(date +"%Y-%m-%d %H:%M:%S")"
done