Вопрос по bash, switch-statement – Что $ {! I} делает в bash? В этом контексте, каков эффект ((i + = 1))?

0

Я не нахожу ничего о значении этого:

case ${!i} in
     --fa)
       ((i+=1))
       fa=${!i}
       ;;

Каково значение${!i}? Каково значение((i+=1))?

@kojiro, ... это одно из тех мест, где действительно хороший ответ очень помогает продемонстрировать ценность вопроса - спасибо за вашу работу над этим вопросом. Charles Duffy
@CharlesDuffy в ретроспективе, это один вопрос: этокак работает этот код вопрос, но это один вопрос. kojiro
Увидетьmywiki.wooledge.org/BashFAQ/006 для (гораздо) больше информации. Charles Duffy
ОП: Я наконец (и думаю, что исчерпывающе) ответил на вашфактический вопрос, а также все объяснил вокруг него. Я делаю этот комментарий, потому что я много отредактировал свой ответ, и вы, возможно, захотите взглянуть еще раз. kojiro

Ваш Ответ

2   ответа
4
Косвенное расширение и поиск имени

косвенное расширение описано ниже.

Если первый символ параметра является восклицательным знаком (!), Вводится уровень косвенной косвенности. Bash использует значение переменной, сформированной из остальной части параметра, в качестве имени переменной; эта переменная затем раскрывается, и это значение используется в остальной части замещения, а не в значении самого параметра. Это известно как косвенное расширение. Исключением являются расширения${!prefix*} а также${!name[@]} описано ниже. Восклицательный знак должен следовать непосредственно за левой скобкой, чтобы ввести косвенность.

Косвенное расширение

Так что если у вас есть декларация, какi=foo и еще какfoo=123Вы можете ссылаться на расширение "foo" следующим образом:

echo ${!i}
Наименование перечисления

Но если вы просто хотите узнать, какие имена начинаются с «i»:

$ iPad=123
$ i=foo
$ echo "${!i*}"
i iPad
Перечисление индекса

И если вы хотите знать, какие индексы (или в bash 4 ассоциативных массивах, ключах) массив имеет:

$ i=(1 2)
$ i[9]=45
$ echo "${!i[@]}"
0 1 9

Обратите внимание, что индексированные массивы в Bash редки!

Арифметическая оценка

Другая часть вашего вопроса - это действительно совершенно другой вопрос о контексте арифметической оценки. Существует несколько контекстов, в которых имена рассматриваются как целые числа.

Если они встречаются как индексы для (неассоциативного) массива. ("${foo[i++]}")Если они встречаются в явном контексте арифметической оценки. ((( i++ )))Послеlet ключевое слово. (let j++ )Если у них естьinteger приписывать. (declare -i)

Символ ($) является необязательным в арифметическом контексте, если это не является двусмысленным. (Было бы неоднозначно использовать$1 без знака доллара.) На самом деле, вы, вероятно, хотите избежать этого, учитывая, что(( $i++ )) это синтаксическая ошибка

Подразумеваемое косвенное расширение

Одним действительно интересным побочным эффектом объявления имени с целочисленным атрибутом является то, что оно подразумевает форму косвенного расширения, отличную от${!name} выражение:

$ aname=123
$ anothername=aname
$ echo $anothername
aname
$ declare -i anothername
$ anothername=aname
$ echo $anothername
123

Что на самом деле здесь происходит, это когдаanothername объявляется как целое число, выражения присваивания имеют арифметический контекст наПравая сторона, Даже еслиaname не был явно объявлен как целое число, здесь он рассматривается как единое целое.

$ anothername=aname++
$ echo $anothername $aname
123 124

Для получения дополнительной информации см. АРИФМЕТИЧЕСКАЯ ОЦЕНКА в руководстве по bash.

Ваш код:
case ${!i} in
     --fa)
       ((i+=1))
       fa=${!i}
       ;;

Допустим, вы перебираете варианты, и$3 расширяется до--fa, Но также,i=3, Это заставит "fa" быть установленным вследующий опция в командной строке ($4), так какi=4 тем временемfa назначен.

4

${!i} относится к переменной, имя которой равно значению$i, Это называетсяпеременная косвенность, Смотрите пример, чтобы сделать его более понятным:

$ hello="bye"    # variable $hello contains 'bye'
$ echo "${!i}"   # when doing variable expansion of $i, it fetches $hello
bye

относительно((i+=1))это способ увеличить переменнуюi, Увидеть:

$ i=3
$ ((i+=1))
$ echo $i
4

Вы также можете использовать любой из них:

i=$((i+1))

((i++))

let "i=i+1"

Для дальнейшего ознакомления см.Справочное руководство Bash - Расширение параметров оболочки:

Если первый символ параметра является восклицательным знаком (!), Вводится уровень косвенной косвенности. Bash использует значение переменной, сформированной из остальной части параметра, в качестве имени переменной; эта переменная затем раскрывается, и это значение используется в остальной части замещения, а не в значении самого параметра. Это известно каккосвенное расширение

Похожие вопросы