저는 wget을 사용하여 REST API를 통해 서버에서 정보를 얻는 bash 스크립트를 작성 중입니다. getopts를 사용하여 스크립트에 제공된 옵션을 구문 분석한 다음 if 문을 사용하여 주어진 옵션에 따라 스크립트를 올바르게 리디렉션합니다. 스크립트 본문(예: wget 호출)으로 이동하면 elif는 도움말 메뉴를 인쇄하고 그렇지 않으면 오류 메시지를 인쇄합니다. 그러나 내 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
옵션은 문자열의 길이가 0이 아닌지 확인합니다.
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 ]
세 단어의 목록인 으로 확장됩니다. 왜냐하면 빈 문자열에 대한 분할+glob의 결과는 빈 단어 목록이기 때문입니다. 괄호 사이에 단어가 하나만 있으면 해당 단어가 비어 있지 않으면 조건이 true입니다. 비어 있지 않으므로 조건이 true입니다.[
-n
]
-n
해결책은 다음과 같이 작성하는 것입니다 [ -n "$help" ]
. 비어 있으면 help
4개의 단어, 빈 단어 목록으로 확장됩니다. 이는 null 단어에 연산자를 적용하고 조건은 false입니다.[
-n
]
-n
또 다른 해결책은 을 사용하는 것입니다 [[ -n $help ]]
. 이중 괄호는 구문 분석 규칙이 다른 특수 구문입니다(반면 단일 괄호는 흥미로운 이름을 가진 일반 명령입니다). 대부분의 경우 이중 괄호 내에서 , =
및 의 오른쪽을 제외하고 변수 대체 주위에 큰따옴표를 생략할 수 있습니다 . 원한다면 큰따옴표 생략을 허용하는 예외를 기억할 필요가 없도록 작성할 수 있습니다. 변수 대체 주위에 항상 큰따옴표를 추가하는 것을 기억하세요(그리고 명령 대체 주위에도 마찬가지로: ).==
!=
=~
[[ -n "$help" ]]
"$(foo)"
답변3
여기서는 if/elif가 필요하지 않습니다. 사용법 도움말을 인쇄하고 스크립트를 설정하는 대신 스크립트를 종료하는 함수를 생성하면
-h
옵션이 해당 함수를 호출할 수 있습니다.help=true
usage()
-h
grep
또는 를 사용하여 더 쉽게 수행할 수 있는sed
작업을 수행하기 위해 임베디드 Python 코드를 사용하는 이유는 무엇입니까awk
? 또는jq
어쨌든 코드가 작동하지 않습니다. 당신은 그 의미에 대해 혼란스러워 보입니다
$data
. help 및 getopts 사례 설명에 따르면$data
savedata/issueID
....하지만 URL fetched 를 사용하여 콘텐츠를 저장한다고 가정하고 있는 것 같습니다wget
.실제로 해당 데이터/문제 ID를 사용하지 않는 것 같습니다
-d
. 요청의 쿼리 문자열에 이를 포함해야 할까요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