我正在构建一个 bash 脚本,该脚本使用 wget 通过 REST api 从服务器获取信息。我使用 getopts 解析提供给脚本的选项,然后使用 if 语句根据给定的选项正确重定向脚本。 if 转到脚本的主体(即 wget 调用),elif 打印帮助菜单,else 打印错误消息。然而我的 elif 似乎充当了 else 语句。当我跑步时:
>./jira -h
我得到了正确的响应,即帮助菜单:
----------jira options----------
Required:
-d [data/issueID]
-u [username] -> [username] is your JIRA username
-p [password] -> [password] is your JIRA password
Optional:
-q -> quiet, i.e. no output to console
-h -> help menu
然而,当我运行一些应该给我错误消息的东西时,我会得到帮助菜单:
>./jira -u jsimmons
----------jira options----------
Required:
-d [data/issueID]
-u [username] -> [username] is your JIRA username
-p [password] -> [password] is your JIRA password
Optional:
-q -> quiet, i.e. no output to console
-h -> help menu
我的脚本如下:
#!/bin/bash
#using getopts to parse options
while getopts ":hqd:u:p:" opt; do
case $opt in
h)
help="true"
;;
q)
quiet="true"
;;
d)
data=$OPTARG
;;
u)
username=$OPTARG
;;
p)
password=$OPTARG
;;
\?)
echo "Invalid option: -$OPTARG" >&2
;;
:)
echo "Option -$OPTARG requires an argument." >&2
;;
esac
done
#check if required options have been set
if [[ -n $data && -n $username && -n $password ]]; then
wget -q \
--http-user=$username \
--http-passwd=$password \
--header="Content-Type: application/json" [URI]
#placing issue info into variable
response=$(< $data)
#using heredoc to run python script
#python script uses regular expressions to find the value of the field
#customfield_10701 ie the branch version
output=$(python - <<EOF
import re
matchObj = re.search(
r'(?<=customfield_10701":").*(?=","customfield_10702)',
'$response',
re.I
)
if(matchObj):
print(matchObj.group())
EOF
)
#writes branch version in .txt file
echo $output>branchversion.txt
#prints the branch version if the quiet option hasn't been set
if [ -z $quiet ]; then
echo "-------------------------------------------"
echo ""
echo "The branch version for issue $data is:"
cat branchversion.txt
echo ""
fi
#removes file that wget creates containing all data members for the issue
rm $data
elif [ -n $help ]; then
#if help option has been set
echo ""
echo "----------jira options----------"
echo "Required:"
echo "-d [data/issueID]"
echo "-u [username] -> [username] is your JIRA username"
echo "-p [password] -> [password] is your JIRA password"
echo ""
echo "Optional:"
echo "-q -> quiet, i.e. no output to console"
echo "-h -> help menu"
echo ""
#http GET data members for issue
else
#if not all required options or help have been set
echo "Error: Missing argument(s)"
echo "Usage: ./jira [option(s)] -d [data] -u [username] -p [password]"
echo ""
echo "Try: ./jira -h for more options"
fi
答案1
该-n
选项检查字符串的长度是否非零。
if [ ... ]; then #posix compliant condition tests
if [[ ... ]]; then #extended condition tests
扩展条件测试的工作方式似乎与 posix 不同。
> if [ -n $unsetVar ];then echo yes ; fi
yes
>
> if [ -n "$unsetVar" ];then echo yes ; fi
>
> if [[ -n $unsetVar ]];then echo yes ; fi
>
要么对两者使用扩展条件[[ ... ]]
,要么将变量括在引号中。目前你的elif
陈述总是正确的。
答案2
根本问题是您省略了变量替换周围的双引号。在大多数情况下,当您编写 时$help
,这并不意味着“获取 的值help
”,而是意味着“获取 的值help
,将其解释为以空格分隔的通配符模式列表,并将每个模式替换为匹配文件的列表如果至少有一个文件名匹配,则命名”。
当help
为空时,展开为三个单词, ,[ -n $help ]
的列表,因为对空字符串进行 split+glob 的结果是一个空单词列表。当括号之间只有一个单词时,除非该单词为空,否则条件为真。不为空,因此条件为真。[
-n
]
-n
解决办法是这样写[ -n "$help" ]
:当为空时,它会扩展到四个单词, , 空单词 ,help
的列表。这将运算符应用于空字并且条件为假。[
-n
]
-n
另一种解决方案是使用[[ -n $help ]]
.双括号是特殊的语法,具有不同的解析规则(而单括号是具有有趣名称的普通命令)。在大多数情况下,在双括号内,您可以在变量替换周围省略双引号,但 、=
和的右侧除外。如果您愿意,您可以编写,因此您不需要记住允许省略双引号的例外情况:只需记住始终在变量替换周围添加双引号(以及类似地在命令替换周围添加双引号:)。==
!=
=~
[[ -n "$help" ]]
"$(foo)"
答案3
这里甚至不需要 if/elif 。创建一个打印使用帮助并退出脚本的函数,而不是
-h
设置,然后该选项就可以调用该函数。help=true
usage()
-h
grep
为什么你使用嵌入式 python 代码来完成可以更轻松地使用or完成的sed
工作awk
?或者jq
无论如何你的代码都不会工作。你似乎对其中的含义感到困惑
$data
。根据帮助和 getopts case 语句,$data
保存data/issueID
....但看起来您假设它保存使用 获取的 URL 的内容wget
。事实上,看起来您甚至没有使用该
-d
data/issueID...也许您应该将其包含在请求的查询字符串中wget
?或者
-d
应该有一个文件名作为参数?从帮助信息来看,这似乎不太可能。
无论如何,这是一个解决了大部分问题的版本(并且,在我看来,大大提高了脚本的可读性):
#!/bin/bash
URI='...whatever...'
usage() {
# print optional error message and help message and exit.
[ -z "$*" ] || printf "%s\n\n" "$*"
# or, if you don't want help printed with every error message:
# [ -z "$*" ] || printf "%s\n\nUse -h option for help.\n" "$*" && exit 1
cat >&2 <<__EOF__
----------jira options----------
Required:
-d [data/issueID]
-u [username] -> [username] is your JIRA username
-p [password] -> [password] is your JIRA password
Optional:
-q -> quiet, i.e. no output to console
-h -> help menu
__EOF__
exit 1
}
quiet=''
#using getopts to parse options
while getopts ":hqd:u:p:" opt; do
case $opt in
h) usage ;;
q) quiet='true' ;;
d) data="$OPTARG" ;;
u) username="$OPTARG" ;;
p) password="$OPTARG" ;;
\?) usage "Invalid option: -$OPTARG" ;;
:) usage "Option -$OPTARG requires an argument." ;;
esac
done
# check for required options
[ -z "$data" ] && usage '-d is required'
[ -z "$username" ] && usage '-u is required'
[ -z "$password" ] && usage '-p is required'
# your embedded python overkill could easily be done with `sed`
# or `awk`. or maybe `jq` as the wget output is json.
# but without a sample of the input I can't provide a guaranteed
# working example. The awk script below is a first attempt at
# extracting the value of `customfield_10701`
wget -q --http-user="$username" \
--http-passwd="$password" \
--header='Content-Type: application/json' \
-O -
"$URI" |
awk -F': ' '/"customfield_10701"/ {
gsub(/[",]/,"",$2);
print $2
}' > branchversion.txt
# alternatively, if you have `jq` installed, try piping wget's
# output through something like `jq -r .customfield_10701` instead of awk.
#prints the branch version if the quiet option hasn't been set
if [ -z "$quiet" ]; then
echo "-------------------------------------------"
echo ""
echo "The branch version for issue $data is:"
cat branchversion.txt
echo ""
fi