【问题标题】:script not reading last line of a file脚本未读取文件的最后一行
【发布时间】:2013-06-19 15:06:04
【问题描述】:

我在 Windows 中使用记事本创建了一个文件:

    26453215432460
    23543265235421

    38654365876325


    12354152435243

我有一个脚本可以读取每一行,并在其他文件中为每一行创建如下命令,并且不会考虑空行:

    CRE:EQU,264532154324600,432460,1;

现在如果我在数字12354152435243的最后一行之后按回车键保存我的输入文件,那么输出文件包含上面对应于所有数字的命令(包括最后一个12354152435243

    CRE:EQU,264532154324600,432460,1;
    CRE:EQU,235432652354210,235421,1;
    CRE:EQU,386543658763250,876325,1;
    CRE:EQU,123541524352430,435243,1;

但是如果我保存文件,在输入最后一个数字后没有按回车,即在此12354152435243 之后,那么在脚本执行后,我看不到输出文件有最后一个数字的命令:

    CRE:EQU,264532154324600,432460,1;
    CRE:EQU,235432652354210,235421,1;
    CRE:EQU,386543658763250,876325,1;

谁能解释代码中的错误:

    while read LINE
    do
    [ -z "$LINE" ] && continue
    IMEI=`echo $LINE | sed 's/ //g' | sed -e 's/[^ -~]//g'`
    END_SERIAL=`echo $IMEI | cut -c9- | sed 's/ //g' | sed -e 's/[^ -~]//g'`
    echo "CRE:EQU,${IMEI}0,${END_SERIAL},${list},,${TODAY};" >> /apps/ins/list.out
    done < "${FILE_NAME}"

请帮忙

【问题讨论】:

  • 我想知道这是否与 Windows 与 *nix 行尾有关。 (可能不是,但你永远不知道...)尝试在 HexFiend 等十六进制编辑器中打开文件,然后查看最后一个字符。
  • 是的,我想的是回车或\n 字符
  • 好吧,你也许可以将行尾更改为 Unix 行尾而不是 Windows 行尾。
  • 在获取输入文件后,我已经在脚本中添加了dos2unix。你的意思是,这不会解决它?
  • 记事本有个愚蠢的想法,即最后一行不需要 any 类型的终结符。如果您不确定以换行符手动结束文件,它所保存的内容在技术上不是有效的文本文件,因为文本文件由带有终止符的行组成。

标签: linux shell unix


【解决方案1】:

使用

grep . "${FILE_NAME}" | while read LINE

while read LINE
do
....
done < <(grep . "${FILE_NAME}")

grep 对行尾不太敏感,您将免费获得空行跳过... :)

老实说,从来没有尝试过 windows,以上都适用于 unix...

编辑说明:

制作下一个文件:

echo -n -e 'line\n\nanother\nno line ending here>' >file.txt

该文件包含 4 行(尽管最后“行”不是“正确”行)

line

another
no line ending here>

通常的 shell 例程,如 readwc 寻找行尾。因此,

$ wc -l file.txt 
         3 file.txt

当您搜索''(空字符串)时,grep 会返回找到该字符串的每一行,所以

$ grep '' file.txt

打印

line

another
no line ending here>

当 grep 打印出找到的行时 - 确保最后不存在一个 `\n',所以

$ grep '' file.txt | wc -l

返回

4

因此,对于这些情况,最好将grep-c(计数)一起使用,而不是wc

$ grep -c '' file.txt
4

现在,. 点。点表示任何字符。因此,当您寻找. 时,您会得到所有包含至少一个 字符的行。 因此,它将跳过所有不包含任何字符的行 = 跳过空行。所以,

$ grep . file.txt
line
another
no line ending here>

再次,添加行结束到最后一行(并跳过空行)。请记住,(空格)也是字符,因此当该行仅包含一个空格时,它不是空的。计算非空行

$ grep . file.txt | wc -l
      3

或更快

$ grep -c . file.txt
3

【讨论】:

  • 这很好用。您能不能好心一点,只是为了解释为什么我从 $FILE greppin . 的逻辑。无论如何,非常感谢这个技巧。干杯
  • @Siddharth 补充说明
【解决方案2】:

如果您执行help read,则表示为-d delim continue until the first character of DELIM is read, rather than newline

因此读取将继续,直到遇到\n 或您指定-d delim

所以您可能需要更改分隔符,或者您可以尝试read -e

【讨论】:

  • read -e 不适合我 echo -n $'a\nb' | while read -e x ; do echo $x ; done -ksh: read: -e: unknown option Usage: read [-ACprsv] [-d delim] [-u fd] [-t timeout] [-n nchar] [-N nchar] [var?prompt] [var ...] 还使用 delim-d 选项将增加我的代码以安静几行,因为我必须先复制输入用一个字符作为每个非空行的分隔符的文件,然后我必须将它提供给read -d delim
【解决方案3】:

read 需要行尾来读取输入。试试

echo -n $'a\nb' | while read x ; do echo $x ; done

它只打印a

【讨论】:

  • read -e 不适用于我 echo -n $'a\nb' | while read -e x ; do echo $x ; done -ksh: read: -e: unknown option Usage: read [-ACprsv] [-d delim] [-u fd] [-t timeout] [-n nchar] [-N nchar] [var?prompt] [var ...] 它不适用于 k-shell 吗?
  • @Siddharth:-e 并不重要,我只是在尝试 nkon 的建议。
【解决方案4】:

read 将读取直到找到新行,当它找到新行时,它将返回该行。但如果文件结束时没有换行,read 会将其视为错误。因此,即使 read 已经用 read 到现在的行设置了返回变量,read 的返回码也被设置为指示错误。现在while read ... 这个循环体只有在命令执行成功时才会执行,这里不是这种情况。因此你错过了最后一行。

为了克服这一点,您可以更改条件以检查返回变量是否为空。因此,即使读取失败,条件也会成功,因为变量已经设置到文件末尾。

这与不同操作系统中的行结尾无关,我的意思是它在某种程度上相关,但确切的根本原因始终是 read 无法在行/文件末尾找到新行,最后一行缺少循环体。

下面是一个例子

[[bash_prompt$]]$ echo -ne 'hello\nthere' > log
[[bash_prompt$]]$ while read line; do  echo $line; done < log
hello
[[bash_prompt$]]$ while read line || [ -n "$line" ]; do  echo $line; done < log
hello
there
[[bash_prompt$]]$

【讨论】:

    【解决方案5】:

    为了防止脚本不读取文件的最后一行:

    cat "somefile" | { cat ; echo ; } | while read line; do echo $line; done
    

    来源:我的开源项目https://sourceforge.net/projects/command-output-to-html-table/

    【讨论】:

      猜你喜欢
      • 2014-06-06
      • 2013-03-07
      • 2012-07-22
      • 2019-07-26
      • 1970-01-01
      • 2010-10-15
      • 2012-10-06
      • 1970-01-01
      相关资源
      最近更新 更多