如何区分DOS脚本中的DOS换行符文件

时间:2016-07-26 23:53:29

标签: linux shell unix

我试图编写一个shell脚本,可以确定输入文件中的行是以DOS(CR / LF)还是Unix(LF)换行符结束。

我该如何做出这个决定?

3 个答案:

答案 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