You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

bash中while read仅执行一次且正则匹配失效的技术问题

解决Shell循环仅执行一次的正则匹配问题

问题场景

现有file.txt内容如下:

G9DG1.fqdn.com
G9DG2.fqdn.com
G9DG3.fqdn.com
G9DG4.fqdn.com
G9DC1.fqdn.com
G9DC3.fqdn.com
G9DG5.fqdn.com
G9DC4.fqdn.com

尝试用以下while read脚本逐行检查主机名是否匹配正则G[0-9]{1,2}[DS]C[0-9]{1,3}.fqdn.com:

while read -r line
do
    if [[ "$line" == "$(grep -E 'G[0-9]{1,2}[DS][C][0-9]{1,3}.fqdn.com')" ]]

    then
        echo "$line matches"
    else
        echo "$line doesn't match"
    fi
done < file.txt

但脚本仅输出第一行结果就退出:

G9DG1.fqdn.com doesn't match

期望输出应该是逐行判断的结果:

G9DG1.fqdn.com doesn't match
G9DG2.fqdn.com doesn't match
G9DG3.fqdn.com doesn't match
G9DG4.fqdn.com doesn't match
G9DC1.fqdn.com matches
G9DC3.fqdn.com matches
G9DG5.fqdn.com doesn't match
G9DC4.fqdn.com matches

问题原因

  1. 标准输入被耗尽:脚本中grep命令未指定输入文件,默认读取标准输入(即file.txt)。第一次循环时,grep会读取整个file.txt内容,导致后续read命令无剩余内容可读取,循环直接终止。
  2. 匹配逻辑错误:用==将单行的$line与grep输出的多行结果做比较,逻辑不成立,无法正确判断单行是否匹配正则。

解决方案

方法1:使用Bash内置正则匹配

直接用Bash的[[ $line =~ 正则表达式 ]]语法,无需调用外部grep命令,避免标准输入冲突:

while read -r line
do
    if [[ "$line" =~ ^G[0-9]{1,2}[DS]C[0-9]{1,3}\.fqdn\.com$ ]]
    then
        echo "$line matches"
    else
        echo "$line doesn't match"
    fi
done < file.txt

注意:正则中的.需转义为\.,否则会匹配任意字符;加上^和$确保整行完全匹配,避免部分匹配。

方法2:让grep读取指定内容而非标准输入

如果坚持用grep,可以通过管道将当前行传给grep,并用-q参数静默判断(更高效):

while read -r line
do
    if echo "$line" | grep -qE '^G[0-9]{1,2}[DS]C[0-9]{1,3}\.fqdn\.com$'
    then
        echo "$line matches"
    else
        echo "$line doesn't match"
    fi
done < file.txt

-q参数让grep仅返回退出状态码,不输出内容,适合条件判断场景。

验证结果

执行上述任一修正后的脚本,都会输出期望的逐行判断结果。

内容的提问来源于stack exchange,提问作者Saeed

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 15:40:10