/bin/sh:解析命令行参数导致:shift:不能移动那么多
/bin/sh: parsing command line arguments results in: shift: can't shift that many
我需要自己解析命令行参数,而不是依赖 getopt
或其他函数。
我的脚本(下面进行了简化)采用可选参数 -P
,后跟模式,然后是文件名:
./myscript -P "pattern" file.txt
命令行参数可以任意顺序,./myscript file.txt -P "pattern"
是允许的。但是 -P
后面必须始终跟有模式。
我面临的问题是,当提供 -P
时,我需要“吃掉”下一个参数,这样它就不会被解释为文件名。所以我使用 shift
。但似乎 for
循环已经读入了原始的 $@
数组,所以即使我移动,它仍然迭代“模式”,并将其解释为文件。
所以我有 3 次而不是 2 次 for 循环迭代:
# 1. cycle:
arg = -P
$@ = -P pattern file
pattern =
file =
# 2. cycle:
arg = pattern
$@ = file
pattern = pattern
file =
3. cycle
arg = file
$@ =
pattern = pattern
file = pattern
我的预期是,for 循环应该是 运行 两次:-P
和 file
。相反,它是 运行 3 次,我得到这个错误:
shift: can't shift that many
我该如何解决这个问题?
#!/bin/sh
f=
pattern=
for arg do
echo arg = $arg
echo $\@ = $@
echo pattern = $pattern
echo file = $f
echo
shift
case "$arg" in
(-P)
if [ -n "" ] ; then
pattern=""
shift
else
printf "\nError: -P needs an argument\n\n" >&2
exit 1
fi
;;
(*)
if [ -z "$f" ] ; then
f="$arg"
else
printf "\nError: too many arguments: $f $arg\n\n" >&2
exit 1
fi
;;
esac
done
for 循环保留其自己的位置参数列表的私有副本,您无法使用 shift
或 set
(请参阅 )更改该副本。
改为使用 while 循环。
parse_args()
while test $# -gt 0; do
case in
(-P)
p=
shift ;;
(*)
f=
esac
shift
done
p= f=
parse_args "$@"
我需要自己解析命令行参数,而不是依赖 getopt
或其他函数。
我的脚本(下面进行了简化)采用可选参数 -P
,后跟模式,然后是文件名:
./myscript -P "pattern" file.txt
命令行参数可以任意顺序,./myscript file.txt -P "pattern"
是允许的。但是 -P
后面必须始终跟有模式。
我面临的问题是,当提供 -P
时,我需要“吃掉”下一个参数,这样它就不会被解释为文件名。所以我使用 shift
。但似乎 for
循环已经读入了原始的 $@
数组,所以即使我移动,它仍然迭代“模式”,并将其解释为文件。
所以我有 3 次而不是 2 次 for 循环迭代:
# 1. cycle:
arg = -P
$@ = -P pattern file
pattern =
file =
# 2. cycle:
arg = pattern
$@ = file
pattern = pattern
file =
3. cycle
arg = file
$@ =
pattern = pattern
file = pattern
我的预期是,for 循环应该是 运行 两次:-P
和 file
。相反,它是 运行 3 次,我得到这个错误:
shift: can't shift that many
我该如何解决这个问题?
#!/bin/sh
f=
pattern=
for arg do
echo arg = $arg
echo $\@ = $@
echo pattern = $pattern
echo file = $f
echo
shift
case "$arg" in
(-P)
if [ -n "" ] ; then
pattern=""
shift
else
printf "\nError: -P needs an argument\n\n" >&2
exit 1
fi
;;
(*)
if [ -z "$f" ] ; then
f="$arg"
else
printf "\nError: too many arguments: $f $arg\n\n" >&2
exit 1
fi
;;
esac
done
for 循环保留其自己的位置参数列表的私有副本,您无法使用 shift
或 set
(请参阅
改为使用 while 循环。
parse_args()
while test $# -gt 0; do
case in
(-P)
p=
shift ;;
(*)
f=
esac
shift
done
p= f=
parse_args "$@"