而read循环忽略文件中的最后一行

时间:2014-08-14 21:43:03

标签: bash

读取一个文件,members_08_14.csv只包含一个数字列表,while循环正在读取每一行。对于每一行,该数字与正则表达式匹配,以确保它只是数字和正好11个字符。

while read card
do
    if [[ $card =~ ^[0-9]{11}$ ]]
    then
        echo "some sql statement with $card" >> temp.sql;
    else
        echo "Invalid card number in file: $card";
    fi
done <registered/members_08_14.csv

有趣的是,如果正则表达式不匹配,则不会执行else。我希望将该行写入temp.sql,或者将一行打印到stdout,表示该卡号无效。

然而,行为更像是true条件或仅为整个文件激活false条件。为什么会这样?

以下是已注册/ members_08_14.csv的内容:

47678009583
47678009585
47678009587
47678009590
476780095905

第一行有效,第5行无效。

cat -vte registered/members_08_14.csv

的输出
47678009583$
47678009585$
47678009587$
47678009590$
476780095905$

2 个答案:

答案 0 :(得分:3)

如果文件的最后一行末尾没有换行符,read会将其内容放入card - 但会以非零值退出。因为在这种情况下read已退出非零值,所以while循环将退出而不会继续运行正则表达式的语句。

最简单的解决方法是更正文件。

您可以采取的另一种方法是忽略read实际填充其目标时的退出状态(并在此时将$'\r'放入IFS,以便read将忽略DOS换行符中的额外字符):

while card=; IFS=$' \t\r\n' read -r card || [[ $card ]]; do
    if [[ $card =~ ^[0-9]{11}$ ]]
    then
        echo "some sql statement with $card" >> temp.sql;
    else
        echo "Invalid card number in file: $card";
    fi
done <registered/members_08_14.csv

答案 1 :(得分:2)

也许你的文件是DOS格式,你也可以在变量的末尾读取回车符(\r)。尝试运行dos2unix filesed -i 's|\r||' file。另一种方法是在每次输入后通过此

删除该字符
while IFS=$' \t\r\n' read -r card