我试图编写一个shell脚本,可以确定输入文件中的行是以DOS(CR / LF)还是Unix(LF)换行符结束。
我该如何做出这个决定?
答案 0 :(得分:1)
避免依赖file
之类的外部工具的一种方法如下:
#!/bin/bash
# ^^^^- important! not /bin/sh, and do not run with "sh scriptname"
# if given a command-line argument, redirect from it as stdin
if [ -n "$1" ]; then
exec <"$1" || exit
fi
# Read a single line from stdin into a variable
if ! IFS= read -r line; then
# we were unable to read a line
echo "Invalid or Empty"
exit 1
fi
# Check whether the last character of that line is a CR
case $line in
*$'\r') echo "DOS" ;;
*) echo "UNIX" ;;
esac
这是有效的,因为在bash中(虽然不是POSIX sh),$'\r'
是回车符(CR)的语法。由于read
读取到第一个看到的LF,在DOS文件中,从该文件读取的行中的最后一个字符将是CR。
答案 1 :(得分:1)
如果检查第一行就足够了,比如
perl -ne 'exit ($_ =~ /\r$/)' file
你可以在Bash中做同样的事情;
lffile () {
local REPLY
read -r <"$1"
case $REPLY in *$'\r') return 1;; *) return 0;; esac
}
这需要$'\r'
C风格的字符串Bash&gt; = 3.x.如果您可以在脚本中可靠且可移植地嵌入文字回车符,则甚至可以使用sh
进行此次微小更改。以下使用一个讨厌的全局来保存回车符:
lffile_cr=$(printf '\r')
lffile () {
# local is not POSIX; simply overwrite REPLY
read -r <"$1"
case $REPLY in *"$lffile_cr") return 1;; *) return 0;; esac
}
在最一般的情况下,文件可能有混合行结尾,但是如果我们假设行结尾是一致的(和/或对于那个模糊的角落情况获得50%的命中率或未命中率是可以接受的),请阅读第一行就足够了。
答案 2 :(得分:0)
你可以从
开始 last2=`tail -c 2 your_file | od -x -A n`
这将your_file的最后两个字节的十六进制表示存储在变量last2中。唯一的问题是字节顺序。在big-endian机器上,它将是0a0d,并且在小端机器0d0a上。
现在您可以根据硬件的字节顺序编写测试,也可以作弊写作
if [ $last2 = 0a0d -o $last2 = 0d0a ]
then
# Cheating! If the file ends in LFCR, it would incorrectly
# say that it is CRLF
echo File ends in CRLF
fi