我将一些日期参数放入脚本
MySqlDataAdapter.SelectCommand.CommandTimeout = 600
在set-x上我进入无限循环。它今天永远不会打印出来。我通过shellcheck运行它,它说它没问题。
#!/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
答案 0 :(得分:5)
是的,非常明显,位置参数count $#
将始终是传递的参数数量,除非你对它进行等效的减量操作,循环永远不会退出。
您需要在shift
条件之后使用else
,以便将位置参数移动1,然后循环决定是否还有其他参数需要处理。
你最终进入了这个循环,因为首先使用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
答案 1 :(得分:3)
错误来自循环中缺少shift
,阻止循环查看所有命令行参数。
建议:
#!/bin/sh
fmt='%Y%m%d'
when='now'
while [ "$#" -ne 0 ]; do
case "$1" in
-t|--test) # or just: -t|--t*)
fmt="$fmt.test" ;;
-y|--yesterday) # or just: -y|--y*)
if [ "$(date +%u)" -eq 1 ]; then
when='3 days ago' # or 'last friday'
else
when='yesterday 13:00'
fi ;;
[!-]*) break ;; # non-option detected, break out of loop
--) shift; break ;; # explicit end of options detected, break
*) echo 'Error in command line options' >&2
exit 1
esac
shift
done
today=$(date --date="$when" +"$fmt")
echo "$today"
这是相同的脚本,但是我选择使用case ... esac
而不是if
语句来查看参数,除了更容易阅读之外,还允许您支持缩写命令行选项(参见代码中的注释)。
我还将today
的最终设置移到脚本的末尾,并且只在循环中设置when
和fmt
。请注意,这可以让您同时使用--test
和--yesterday
。
如果您的脚本不需要长选项,可以编写
#!/bin/sh
fmt='%Y%m%d'
when='now'
while getopts 'ty' opt; do
case "$opt" in
t)
fmt="$fmt.test" ;;
y)
DOW=$(date +%u)
if [ "$(date +%u)" -eq 1 ]; then
when='3 days ago'
else
when='yesterday 13:00'
fi ;;
*) echo 'Error in command line options' >&2
exit 1
esac
done
shift "$(( OPTIND - 1 ))"
today=$(date --date="$when" +"$fmt")
echo "$today"
这样就可以使用-ty
同时指定-t
和-y
。
只有在稍后需要在脚本中使用命令行中的非选项参数时才需要最后的shift
。
由于上述脚本未使用bash
特定内容,因此我选择使用/bin/sh
运行它们。
答案 2 :(得分:1)
或使用棘手的getopt
命令:
#!/bin/bash
tmp=$(getopt -o ty --long test,yesterday -- "$@")
[[ $? -eq 0 ]] || exit
eval set -- "$tmp"
date_fmt="+%Y%m%d"
while true; do
case $1 in
-t|--test)
today=$(date "$date_fmt").test
shift
;;
-y|--yesterday)
dow=$(date +%w) # (0..6), 0 is Sunday
if (( $dow <= 1 )); then
rel_date="last friday"
else
rel_date=yesterday
fi
today=$(date -d "$rel_date" "$date_fmt")
shift
;;
--) shift; break ;;
*) echo "Oops, something is wrong" >&2; exit 2 ;;
esac
done
echo "${today:=$(date "$date_fmt")}"