【问题标题】:How to detect file ends in newline?如何检测文件以换行符结尾?
【发布时间】:2010-09-07 12:20:12
【问题描述】:

Can you modify text files when committing to subversion?Grant 建议我阻止提交。

但是我不知道如何检查文件是否以换行符结尾。如何检测文件以换行符结尾?

【问题讨论】:

    标签: svn bash text-files


    【解决方案1】:

    @Konrad:tail 不返回空行。我制作了一个文件,其中包含一些不以换行符结尾的文本和一个以换行符结尾的文件。这是tail的输出:

    $ cat test_no_newline.txt
    this file doesn't end in newline$ 
    
    $ cat test_with_newline.txt
    this file ends in newline
    $
    

    虽然我发现 tail 有获取最后一个字节的选项。所以我修改了你的脚本:

    #!/bin/sh
    c=`tail -c 1 $1`
    if [ "$c" != "" ]; then
        echo "no newline"
    fi
    

    【讨论】:

    • 这个答案不是最优的,因为我不知道你指的是哪个康拉德。
    • [ "$c" != "" ]false 用于完全空的文件,这与我的预期相反。
    • 如果最后一个字节是空字节,这也会失败。您无法在命令替换中区分“空”和“以换行符结尾”,这会修剪最后的换行符。
    【解决方案2】:

    一个完整的 Bash 解决方案,只有 tail 命令,也可以正确处理空文件。

    #!/bin/bash
    # Return 0 if file $1 exists and ending by end of line character,
    # else return 1
    [[ -s "$1" && -z "$(tail -c 1 "$1")" ]]
    
    • -s "$1" 检查文件是否为空
    • -z "$(tail -c 1 "$1")" 检查其最后一个(现有)字符是否为行尾字符
    • 返回所有[[...]]条件表达式

    您还可以定义此 Bash 函数以在您的脚本中使用它。

    # Return 0 if file $1 exists and ending by end of line character,
    # else return 1
    check_ending_eol() {
        [[ -s "$1" && -z "$(tail -c 1 "$1")" ]]
    }
    

    【讨论】:

      【解决方案3】:

      您可以使用tail -c 1 获取文件的最后一个字符。

         my_file="/path/to/my/file"
      
         if [[ $(tail -c 1 "$my_file") != "" ]]; then
            echo "File doesn't end with a new line: $my_file"
         fi
      

      【讨论】:

        【解决方案4】:

        我正在对自己的答案进行更正。

        以下应该在所有情况下都可以正常工作,没有失败:

        nl=$(printf '\012')
        nls=$(wc -l "${target_file}")
        lastlinecount=${nls%% *}
        lastlinecount=$((lastlinecount+1))
        lastline=$(sed ${lastlinecount}' !d' "${target_file}")
        if [ "${lastline}" = "${nl}" ]; then
            echo "${target_file} ends with a new line!"
        else
            echo "${target_file} does NOT end with a new line!"
        fi
        

        【讨论】:

          【解决方案5】:

          read 命令无法读取没有换行符的行。

          if tail -c 1 "$1" | read -r line; then
            echo "newline"
          fi
          

          另一个答案。

          if [ $(tail -c 1 "$1" | od -An -b) = 012 ]; then
            echo "newline"
          fi
          

          【讨论】:

            【解决方案6】:

            甚至更简单:

            #!/bin/sh
            test "$(tail -c 1 "$1")" && echo "no newline at eof: '$1'"
            

            但如果您想要更稳健的检查:

            test "$(tail -c 1 "$1" | wc -l)" -eq 0 && echo "no newline at eof: '$1'"
            

            【讨论】:

            • 不可信,因为它无法区分 EOL 和任何其他空格字符。
            • @akim 现在已修复。
            • 这仍然失败,例如如果最后一个字符是空字节。
            • 很好。对此进行额外检查。
            【解决方案7】:

            这是一个有用的 bash 函数:

            function file_ends_with_newline() {
                [[ $(tail -c1 "$1" | wc -l) -gt 0 ]]
            }
            

            你可以像这样使用它:

            if ! file_ends_with_newline myfile.txt
            then
                echo "" >> myfile.txt
            fi
            # continue with other stuff that assumes myfile.txt ends with a newline
            

            【讨论】:

            • 这应该是公认的答案;它适用于空文件、以空字节结尾的文件和常规文件。到wc -l 的管道有点不吸引人,但它确实做了正确的事情——它计算文件最后一个字节中换行符的数量。如果不是一个,则文件不会以换行符结尾。
            【解决方案8】:

            为我工作:

            tail -n 1 /path/to/newline_at_end.txt | wc --lines
            # according to "man wc" : --lines - print the newline counts
            

            所以 wc 计算换行符的数量,这在我们的例子中很好。 oneliner 根据文件末尾是否存在换行符打印 0 或 1。

            【讨论】:

              【解决方案9】:

              仅使用bash:

              x=`tail -n 1 your_textfile`
              if [ "$x" == "" ]; then echo "empty line"; fi
              

              (注意正确复制空格!)

              @grom:

              tail 不返回空行

              该死的。我的测试文件不是以\n 结束,而是以\n\n 结束。显然vim 不能创建不以\n (?) 结尾的文件。无论如何,只要“获取最后一个字节”选项有效,一切都很好。

              【讨论】:

                【解决方案10】:

                你可以使用这样的东西作为你的预提交脚本:

                #! /usr/bin/perl 而(){ $最后 = $_; } if (! ($last =~ m/\n$/)) { print STDERR "文件不以 \\n!\n"; 1号出口; }

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 2017-10-02
                  • 1970-01-01
                  • 2017-03-01
                  • 2010-11-03
                  • 2016-08-13
                  • 2013-07-12
                  • 1970-01-01
                  相关资源
                  最近更新 更多