我有以下代码:
while getopts ":p:t:n:" o; do
case "${o}" in
p)
p=${OPTARG}
numep=$p
mkdir $numep
;;
t)
t=${OPTARG}
tip=$t
if [ $tip == "c" ]; then
touch $numep/$numep.c
touch $numep/$numep.h
elif [ $tip == "c++" ]; then
touch $numep/$numep.cpp
touch $numep/$numep.h
fi
;;
n)
n=${OPTARG}
nrFis=$n
if [ $tip == "c" ]; then
for i in $(seq $n); do
touch $numep/src/$numep$i.c
touch $numep/inc/$numep$i.h
done
elif [ $tip == "c++" ]; then
for i in $(seq $n); do
touch $numep/src/$numep$i.cpp
touch $numep/inc/$numep$i.h
done
fi
;;
*)
err-help
;;
esac
done
err-help是一个先前定义的函数,它为正确的调用提供指令。
正确调用脚本如下所示:./script.sh -p project_name -t project_type -n source_files_number
我想做什么:为c或c ++项目创建一个包含特定数量源文件的目录。
我的问题:如何使用$ {OPTARG}? p = $ {OPTARG}究竟是什么东西? p,t,n变量是否会填充正确的内容? 我该怎么做呢,拜托? :(
答案 0 :(得分:3)
您正在使用getopts
,但您正在假设您将查看选项的顺序。稍后会详细介绍。
让我们看一下help getopts
OPTSTRING包含要识别的选项字母; 如果是一封信 后跟一个冒号,该选项应该有一个参数, 白色空间应该与它分开。
......当一个选项需要参数时, getopts将该参数放入shell变量OPTARG 。
这是getopts的神奇之处。由于您在optstring中添加了p:
,因此当$0
=“p”时,变量$OPTARG
将包含您向-p
提供的任何内容,在本例中为字符串“project_name”
现在进行一些代码审查:
case "${o}" in
p)
p=${OPTARG}
numep=$p
mkdir $numep
;;
如果您正在使用数组,则只需要使用大括号,或者您需要从周围文本($o_x
vs ${o}_x
中消除变量名称的歧义)写起来会更整洁
case "$o" in ...
您无需创建与选项同名的特殊变量。你永远不会使用$p
。你可以写
numep="$OPTARG"
始终引用您的变量。总是。除非你明确知道何时不加引号。如果我提供-p "some dir with spaces"
,则mkdir $numep
将创建 4 目录。你需要写
mkdir "$numep"
如果$ numep目录已经存在,您将收到错误消息。如果您不想这样做,请使用mkdir -p "$numep"
(请参阅man mkdir
)
现在,请解决我的第一个问题:调用脚本并在任何订单中提供选项
没有任何问题./script.sh -t project_type -n source_files_number -p project_name
您的选项解析假定您已在t
和n
分支中设置了$ numep,因此您假设用户首先提供了-p
。如果-t
首先出现,则$ numep为空,您将尝试创建文件/.h
。即使您有权写入根目录,这也不是您想要做的。在开始做事之前,先解析所有你的选择。
我会这样写:
while getopts ":p:t:n:" o; do
case "$o" in
p) numep="$OPTARG" ;;
t) case "$OPTARG" in
c) ext="c" ;;
"c++") ext="cpp" ;;
*) echo "Error: use 'c' or 'c++' for -t option" >&2
exit 1
;;
esac
;;
n) nrFis="$OPTARG" ;;
*) err-help ;;
esac
done
mkdir -p "$numep"
touch "$numep/$numep.$ext"
touch "$numep/$numep.h"
for ((i=1; i<=$nrFis; i++)); do
touch "$numep/src/$numep$i.$ext"
touch "$numep/inc/$numep$i.h"
done