Intereting Posts
Sylpheed не выполняет автоматическую проверку учетных записей IMAP Как заблокировать оскорбительные IP-адреса с помощью pf в OpenBSD? выберите несколько столбцов на основе диапазонов, указанных в отдельном файле Как определить, какой скрипт выполняется bash? Прикрепление файла в Unix для данной строки, а затем другой набор строк в этом файле и печать свойств файла тоже Перенос операционной системы с виртуальной машины в физическую систему Двоичное представление символической ссылки Почему собственность группы ssh-agent не является root Как я могу запустить команду, подождать 2 секунды и вернуть результат, не убив команду? CentOS, файл PHP работает от браузера, а не от демона cron Когда создавать новую эпоху для пакета Debian? Использование SED для вырезания после 7-го символа каждой строки Как переключиться на bash на DEVISH? Ли Linux автоматически очищает абстрактные сокеты домена? Добавить вариант управления перегрузкой TCP в Linux Ubuntu

Почему мой elif рассматривается как выражение else в моем сценарии bash?

Я создаю скрипт bash, который использует wget для получения информации с сервера с помощью REST api. Я использую getopts для синтаксического анализа параметров, заданных скрипту, а затем используя оператор if, чтобы правильно перенаправить сценарий на основе указанных параметров. Если в главном тексте скрипта (т. Е. Вызове wget), elif печатает меню справки, а else печатает сообщение об ошибке. Однако мой elif, похоже, действует как другое заявление. Когда я запускаю:

>./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, ie 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, ie 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, ie 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 

-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 всегда верно.

Основная проблема заключается в том, что вы опустили двойные кавычки вокруг замены переменных . Когда вы пишете $help , в большинстве контекстов это не означает «принять значение help », это означает «взять значение help , интерпретировать его как список шаблонов подстановок, разделенных пробелами, и заменить каждый шаблон на список совпадающих имен файлов, если совпадает хотя бы одно имя файла ".

Когда help пуст, [ -n $help ] расширяется до списка из трех слов [ , -n , ] , так как результат split + glob на пустой строке представляет собой пустой список слов. Когда между скобками имеется одно слово, условие истинно, если слово не пусто. -n не пусто, поэтому условие истинно.

Исправление состоит в том, чтобы написать [ -n "$help" ] : когда help пуст, это расширяется до списка из четырех слов [ , -n , empty word, ] . Это применит оператор -n к пустому слову, а условие – false.

Альтернативным решением является использование [[ -n $help ]] . В двойных скобках используется специальный синтаксис с различными правилами синтаксического анализа (в то время как одиночные скобки представляют собой обычную команду со смешным именем). Внутри двойных скобок вы можете оставить двойные кавычки вокруг переменных подстановок в большинстве контекстов, исключение составляет правую часть = , == != И =~ . Вы можете написать [[ -n "$help" ]] если вам нравится, поэтому вам не нужно помнить исключения, при которых оставлять двойные кавычки разрешено: просто не забудьте всегда ставить двойные кавычки вокруг переменных подстановок (и аналогично вокруг подстановки команд: "$(foo)" ).

  1. вам даже не нужен if / elif. Вместо -h установите help=true , создайте функцию usage() которая печатает справку об использовании и выходит из скрипта, тогда опция -h может просто вызвать эту функцию.

  2. почему вы используете встроенный код python для выполнения задания, которое легче сделать с помощью grep или sed или awk ? или jq

  3. ваш код не будет работать. Кажется, вы смутились о том, какие $data хранятся. Согласно инструкции справки и оператора getopts, $data содержат data/issueID …. но похоже, что вы предполагаете, что он содержит содержимое URL-адреса, полученного с помощью wget .

    На самом деле, похоже, что вы даже не используете этот -d data / issueID … возможно, вы должны включить его в строку запроса в запросе wget ?

    или -d должен иметь имя файла в качестве аргумента? Из справочного сообщения это кажется маловероятным.


Во всяком случае, вот версия, которая устраняет большинство проблем (и, IMO, значительно улучшает читаемость скрипта):

 #!/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, ie 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 от #!/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, ie 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