Linux 脚本未读取文件的最后一行

Linux 脚本未读取文件的最后一行,linux,shell,unix,Linux,Shell,Unix,我在windows中使用记事本创建了一个文件: 26453215432460 23543265235421 38654365876325 12354152435243 我有一个脚本,它将读取每一行,并在每一行中创建一个类似于其他文件的命令,并且不考虑空白行: CRE:EQU,264532154324600,432460,1; 现在,如果我在最后一行数字123541524352243后按enter键保存输入文件,则输出文件由上面对应于所有数字的命令

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

    26453215432460
    23543265235421

    38654365876325


    12354152435243

我有一个脚本,它将读取每一行,并在每一行中创建一个类似于其他文件的命令,并且不考虑空白行:

    CRE:EQU,264532154324600,432460,1;
现在,如果我在最后一行数字
123541524352243
后按enter键保存输入文件,则输出文件由上面对应于所有数字的命令组成(包括最后一行
12354152435243

    CRE:EQU,264532154324600,432460,1;
    CRE:EQU,235432652354210,235421,1;
    CRE:EQU,386543658763250,876325,1;
    CRE:EQU,123541524352430,435243,1;
但是,如果我保存文件,在键入最后一个数字后(即在此
12354152435243
之后)不按enter键,那么在脚本执行后,我看不到输出文件具有最后一个数字的命令:

    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}"
读取行时
做
[-z“$LINE”]&继续(&C)
IMEI=`echo$LINE | sed's///g'| sed-e's//[^-~]///g'`
END|u SERIAL=`echo$IMEI | cut-c9-| sed's///g'| sed-e's//[^-~]/g'`
echo“CRE:eq,${IMEI}0,${END_SERIAL},${list},${TODAY};”>>/apps/ins/list.out
完成<“${FILE_NAME}”

如果您执行了
帮助阅读,请提供帮助,它说的是for
-d delim将继续,直到读取delim的第一个字符,而不是换行符

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


因此,您可能需要更改delim,或者您可以尝试
read-e

read
需要在行尾读取输入。请尝试

echo -n $'a\nb' | while read x ; do echo $x ; done
它只打印
a

使用

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

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

通常的shell例程,如
read
wc
查找行尾。因此

$ 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
(count)一起使用,而不是
wc

$ grep -c '' file.txt
4
现在,
点。点表示任何字符。因此,当你搜索
时,你会得到至少包含一个字符的所有行。因此,它将跳过所有不包含任何字符的行=跳过空行。因此

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

$ grep . file.txt | wc -l
      3
或者更快

$ grep -c . file.txt
3

read将一直读取,直到找到新行,当它找到新行时,它将返回该行。但是,如果文件结束时没有新行,read会将其视为错误。因此,即使read已将返回变量设置为line 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$]]$
[[bash\u prompt$]$echo-ne'hello\n here'>日志
读取行时[[bash_prompt$]]$;执行echo$行;完成<日志
你好
读取行时[[bash_prompt$]]$;执行echo$行;执行
我想知道这是否与Windows与*nix行结尾有关。(可能不是,但你永远不知道…)请尝试在HexFiend之类的十六进制编辑器中打开该文件,然后查看最后一个字符。是的,我正在考虑使用回车符或
\n
字符。您可能可以将行结尾更改为Unix行结尾,而不是Windows行结尾。在输入文件之后,我的脚本中已经添加了
dos2unix
抓取。你的意思是,这不管用吗?记事本有一个愚蠢的想法,即最后一行不需要任何类型的终止符。如果你不确保手动以换行符结束文件,它保存的内容从技术上讲不是有效的文本文件,因为文本文件是由带终止符的行组成的。
read-e
对我不起作用
echo-n$'a\nb'|读取时-ex;do echo$x;done
-ksh:read:-e:unknown选项
用法:read[-ACprsv][d delim][u fd][t timeout][n nchar][n nchar][var?prompt][var…]
对k-shell不起作用吗?@Siddharth:The
-e
并不重要,我只是在尝试nkon的建议。非常好,这很有效。请您解释一下我为什么在
$文件中使用greppin
的逻辑。非常感谢这个技巧。Cheers@Siddharth添加解释
阅读-e
不适用于我
echo-n$'a\nb'|而read-e x;do echo$x;done
-ksh:read:-e:未知选项用法:read[-ACprsv][d delim][u fd t timeout][n nchar][n nchar][var?prompt][var…]
同时使用
delim
-d
选项将增加我的代码以使几行安静下来,因为我必须首先复制输入文件,每个非空行都有一个字符作为delimeter,然后我必须将其馈送到
read-d delim
$ grep . file.txt
line
another
no line ending here>
$ grep . file.txt | wc -l
      3
$ grep -c . file.txt
3
[[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$]]$