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

Hyp*_*ino 2 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
Run Code Online (Sandbox Code Playgroud)

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

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

这是registered/members_08_14.csv的内容:

47678009583
47678009585
47678009587
47678009590
476780095905
Run Code Online (Sandbox Code Playgroud)

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

输出cat -vte registered/members_08_14.csv

47678009583$
47678009585$
47678009587$
47678009590$
476780095905$
Run Code Online (Sandbox Code Playgroud)

Cha*_*ffy 5

如果文件的最后一行末尾没有换行符,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
Run Code Online (Sandbox Code Playgroud)