Bash脚本使用while循环遍历参数列表陷入无限循环问题求助
解决Bash脚本参数处理的无限循环问题
嗨,我一眼就从你的调试输出里揪出问题了——你的脚本在处理命令行参数时,从来没有消费掉已经处理过的参数!
看调试日志里重复出现的[[ --t = \-\-\t\e\s\t ]]就能明白:每次循环都在检查同一个--t参数,$1的值从来没变过,参数数量$#也一直是1。这样while [ ! $# -eq 0 ]这个循环条件就永远为真,脚本当然会陷入无限循环,根本到不了echo "$today"那一行。
核心解决方案:添加shift命令
shift是Bash里专门用来处理参数列表的命令,它会把所有命令行参数左移一位:原来的$2变成新的$1,$3变成$2,以此类推,同时参数数量$#会减1。只要在每次处理完一个参数后执行shift,就能逐步消耗参数列表,直到$#变成0,循环自然就退出了。
另外,你的脚本开头还有个容易忽略的小错误:#!/bin/bash set -x是错误的写法,shebang行后面的内容会被当作解释器的参数,正确的做法是把set -x单独放在一行。
修改后的完整脚本
这里提供两种写法,你可以根据需求选择:
写法1:在每个参数分支内执行shift
适合需要根据不同参数类型决定是否跳过的场景:
#!/bin/bash set -x today=$(date +%Y%m%d) while [ ! $# -eq 0 ] do if [[ "$1" = "--test" ]] || [[ "$1" = "-t" ]] ; then today=$(date +%Y%m%d).test shift # 消费掉当前的--test/-t参数 elif [[ "$1" = "--yesterday" ]] || [[ "$1" = "-y" ]] ; then DOW=$(date +%u) if [[ "$DOW" = "1" ]] ; then today=$(date --date="3 days ago" +%Y%m%d) else today=$(date -d "yesterday 13:00" +%Y%m%d) fi shift # 消费掉当前的--yesterday/-y参数 else # 遇到未知参数时,可以选择提示后跳过,或者直接报错退出 echo "错误:未知参数 $1" shift fi done echo "$today" exit
写法2:在循环末尾统一执行shift
更简洁,适合大多数常规参数处理场景:
#!/bin/bash set -x today=$(date +%Y%m%d) while [ ! $# -eq 0 ] do if [[ "$1" = "--test" ]] || [[ "$1" = "-t" ]] ; then today=$(date +%Y%m%d).test elif [[ "$1" = "--yesterday" ]] || [[ "$1" = "-y" ]] ; then DOW=$(date +%u) if [[ "$DOW" = "1" ]] ; then today=$(date --date="3 days ago" +%Y%m%d) else today=$(date -d "yesterday 13:00" +%Y%m%d) fi else echo "错误:未知参数 $1" fi shift # 每次循环结束都左移参数列表,统一消费参数 done echo "$today" exit
现在再运行脚本,你会发现参数被逐个处理,循环正常退出,最终能正确输出$today的值啦!
内容的提问来源于stack exchange,提问作者capser
相关产品推荐
相关产品推荐

