【问题标题】:How to find a windows end of line (EOL) character如何查找 Windows 行尾 (EOL) 字符
【发布时间】:2011-07-17 19:41:15
【问题描述】:

我有数百 GB 的数据需要使用 Cygwin 中的 unix paste 实用程序粘贴在一起,但如果文件中有 Windows EOL 字符,它将无法正常工作。数据可能有也可能没有 Windows EOL 字符,如果不需要的话,我不想花时间运行 dos2unix。

所以我的问题是,在 Cygwin 中,我如何才能确定这些文件是否具有 Windows EOL CRLF 字符?

我尝试创建一些测试数据并运行

sed -r 's/\r\n//' testdata.txt

但无论是否运行了 dos2unix,这似乎都匹配。

谢谢。

【问题讨论】:

    标签: linux unix sed eol dos2unix


    【解决方案1】:

    file(1) 实用程序知道其中的区别:

    $ file * | grep ASCII
    2:                                       ASCII text
    3:                                       ASCII English text
    a:                                       ASCII C program text
    blah:                                    ASCII Java program text
    foo.js:                                  ASCII C++ program text
    openssh_5.5p1-4ubuntu5.dsc:              ASCII text, with very long lines
    windows:                                 ASCII text, with CRLF line terminators
    

    file(1) 已经过优化,可以尝试读取尽可能少的文件,因此您可能会很幸运,并且在查找和修复 CRLF 终止符时大大减少了需要执行的磁盘 IO 量。

    请注意,某些情况下的 CRLF 应该保留:SMTP 的捕获将使用 CRLF。但这取决于你。 :)

    【讨论】:

    • 如果结果显示“ASCII 文本,行很长,没有行终止符”
    • 嘿,没有任何行终止符的很长的一行可能是paste(1) 的尴尬输入,但也许file(1) 放弃得太快了?也许这些线比它检查的区域长。 (快速浏览 file 的源代码 (src/file.h) 看起来它检查了 256 KB (HOWMANY),因此听起来您的输入确实缺少很长的行的行终止符。)
    【解决方案2】:
    #!/bin/bash
    for i in $(find . -type f); do
            if file $i | grep CRLF ; then
                    echo $i
                    file $i
                    #dos2unix "$i"
            fi
    done
    

    当您准备好转换它们时,取消注释 "#dos2unix "$i""。

    【讨论】:

      【解决方案3】:

      您可以使用file

      file /mnt/c/BOOT.INI 
      /mnt/c/BOOT.INI: ASCII text, with CRLF line terminators
      

      CRLF 是这里的重要值。

      【讨论】:

        【解决方案4】:

        如果您希望退出代码与sed 不同,则不会。它将根据比赛执行替换或不替换。除非出现错误,否则退出代码将为 true。

        不过,您可以从 grep 获得可用的退出代码。

        #!/bin/bash
        for f in *
        do
            if head -n 10 "$f" | grep -qs $'\r'
            then
                dos2unix "$f"
            fi
        done
        

        【讨论】:

          【解决方案5】:

          grep 递归,带有文件模式过滤器

          grep -Pnr --include=*file.sh '\r$' .
          

          输出文件名、行号和行本身

          ./test/file.sh:2:here is windows line break
          

          【讨论】:

            【解决方案6】:

            如上所述,“文件”解决方案有效。也许下面的代码 sn-p 可能会有所帮助。

            #!/bin/ksh
            EOL_UNKNOWN="Unknown"       # Unknown EOL
            EOL_MAC="Mac"               # File EOL Classic Apple Mac  (CR)
            EOL_UNIX="Unix"             # File EOL UNIX               (LF)
            EOL_WINDOWS="Windows"       # File EOL Windows            (CRLF)
            SVN_PROPFILE="name-of-file" # Filename to check.
            ...
            
            # Finds the EOL used in the requested File
            # $1 Name of the file (requested filename)
            # $r EOL_FILE set to enumerated EOL-values.
            getEolFile() {
                EOL_FILE=$EOL_UNKNOWN
            
                # Check for EOL-windows
                EOL_CHECK=`file $1 | grep "ASCII text, with CRLF line terminators"`
                if [[ -n $EOL_CHECK ]] ; then
                   EOL_FILE=$EOL_WINDOWS
                   return
                fi
            
                # Check for Classic Mac EOL
                EOL_CHECK=`file $1 | grep "ASCII text, with CR line terminators"`
                if [[ -n $EOL_CHECK ]] ; then
                   EOL_FILE=$EOL_MAC
                   return
                fi
            
                # Check for Classic Mac EOL
                EOL_CHECK=`file $1 | grep "ASCII text"`
                if [[ -n $EOL_CHECK ]] ; then
                   EOL_FILE=$EOL_UNIX
                   return
                fi
            
                return
               } # getFileEOL   
               ...
            
               # Using this snippet
               getEolFile $SVN_PROPFILE
               echo "Found EOL: $EOL_FILE"
               exit -1
            

            【讨论】:

              【解决方案7】:

              感谢使用 file(1) 命令的提示,但它确实需要更多改进。我遇到的情况不仅是纯文本文件,而且一些“.sh”脚本都有错误的 eol。并且“文件”将它们报告如下,而不管 eol:

              xxx/y/z.sh: application/x-shellscript
              

              因此需要“file -e soft”选项(至少对于 Linux):

              bash$ find xxx -exec file -e soft {} \; | grep CRLF
              

              这会在目录 xxx 和 subdirs 中找到所有带有 DOS eol 的文件。

              【讨论】:

                【解决方案8】:

                您可以使用 dos2unix 的 -i 选项来获取有关 DOS Unix Mac 换行符(按此顺序)、BOM 和文本/二进制文件的信息,而无需转换文件。

                $ dos2unix -i *.txt
                    6       0       0  no_bom    text    dos.txt
                    0       6       0  no_bom    text    unix.txt
                    0       0       6  no_bom    text    mac.txt
                    6       6       6  no_bom    text    mixed.txt
                   50       0       0  UTF-16LE  text    utf16le.txt
                    0      50       0  no_bom    text    utf8unix.txt
                   50       0       0  UTF-8     text    utf8dos.txt
                

                带有“c”标志的dos2unix 将报告将被转换的文件,iow 文件有DOS 换行符。要报告所有带有 DOS 换行符的 txt 文件,您可以这样做:

                $ dos2unix -ic *.txt
                dos.txt
                mixed.txt
                utf16le.txt
                utf8dos.txt
                

                要仅转换这些文件,您只需执行以下操作:

                dos2unix -ic *.txt | xargs dos2unix
                

                如果您需要对目录进行递归:

                find -name '*.txt' | xargs dos2unix -ic | xargs dos2unix
                

                另见 dos2unix 的手册页。

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2018-07-06
                  • 1970-01-01
                  • 1970-01-01
                  • 2011-02-01
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多