【发布时间】:2021-11-03 05:09:45
【问题描述】:
我需要自己解析命令行参数,而不是依赖getopt或其他函数。
我的脚本(简化如下)采用可选参数-P,后跟一个模式,然后是一个文件名:
./myscript -P "pattern" file.txt
命令行参数可以是任意顺序,./myscript file.txt -P "pattern" 是允许的。但是-P后面一定要跟pattern。
我面临的问题是,当提供-P 时,我需要“吃”下一个参数,以便它不会被解释为文件名。所以我使用shift。但似乎for 循环已经读入了原始的$@ 数组,所以即使我移动,它仍然会遍历“模式”,并将其解释为文件。
所以我有 3 次 for 循环,而不是 2 次迭代:
# 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 "$1" ] ; then
pattern="$1"
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
【问题讨论】:
-
arg 的值是多少?你似乎没有在任何地方设置它
-
我猜这是因为您已经用完了要转移的 args。
-
@joshmeranda - 这是处理命令行参数的标准方法。默认情况下,如果没有指定列表,
for arg do会通过$@。 -
哦,整洁以前没见过。这是docs 的摘录,如果有人想要的话:“如果'in words' 不存在,for 命令会为每个设置的位置参数执行一次命令,就好像'in "$@"' 已被指定"。
标签: shell sh command-line-arguments getopts