首页 > 解决方案 > 使用 while 循环迭代参数列表会进入无限循环

问题描述

我将一些日期参数放入脚本中

#!/bin/bash
set -x
today=$(date +%Y%m%d)
while  [ ! $# -eq 0 ] #while number of arguments is NOT zero, do this
    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
    fi
done

echo "$today"
exit 

在 set-x 上,我进入无限循环。它今天永远不会打印。我通过 shellcheck 运行它,它说没问题。

++ '[' '!' 1 -eq 0 ']'
++ [[ --t = \-\-\t\e\s\t ]]
++ [[ --t = \-\t ]]
++ [[ --t = \-\-\y\e\s\t\e\r\d\a\y ]]
++ [[ --t = \-\y ]]
++ '[' '!' 1 -eq 0 ']'
++ [[ --t = \-\-\t\e\s\t ]]
++ [[ --t = \-\t ]]
++ [[ --t = \-\-\y\e\s\t\e\r\d\a\y ]]
++ [[ --t = \-\y ]]
++ '[' '!' 1 -eq 0 ']'
++ [[ --t = \-\-\t\e\s\t ]]
++ [[ --t = \-\t ]]
++ [[ --t = \-\-\y\e\s\t\e\r\d\a\y ]]
++ [[ --t = \-\y ]]
++ '[' '!' 1 -eq 0 ']'
++ [[ --t = \-\-\t\e\s\t ]]
++ [[ --t = \-\t ]]
++ [[ --t = \-\-\y\e\s\t\e\r\d\a\y ]]
++ [[ --t = \-\y ]]

标签: bashshell

解决方案


是的,不是那么明显,位置参数计数$#将始终是传递的参数数量,除非您对其进行等效的减量操作,否则循环永远不会退出。

您需要shift在条件之后使用,else以便将位置参数移动一,然后循环决定是否还有更多参数需要处理。

您最终进入了这个循环,因为首先使用while循环来处理参数是一个坏主意,应该使用 for 循环

for arg; do

或传统的 C 风格循环

for ((i=1; i<=$#; i++)); do

为了满足您的while循环目的,您可以执行以下操作,但建议这样做。请注意,shift这是您在导致无限循环的原始帖子中缺少的内容。

while [ -n "$1" ]; do
  shift
  # Your code logic goes here
done

推荐阅读