2015-01-06 3 views
3

Учитывая, что Bash Reference Manual в разделе 3.5.3 Shell Parameter Expansion говорит:

${!name[@]} 
${!name[*]} 

Если имя переменной массива, расширяется список индексов массива (ключи), назначенные по имени. Если имя не является массивом, оно увеличивается до 0, если имя задано, а null - в противном случае. Когда используется «@», и расширение появляется в двойных кавычках, каждая клавиша расширяется до отдельного слова.

и

$ {параметр: -слово}

Если параметр не установлен или нулевой, раскрытие слова заменены. В противном случае значение параметра заменяется.

и

$ {параметр: + слово}

Если параметр является нулевым или не установлено, ничего не подменяется, в противном случае раскрытие слова заменены.

Может кто-то объяснить выход из следующих расширений мне:

$ bash --version 
GNU bash, version 3.2.25(1)-release (x86_64-redhat-linux-gnu) 
Copyright (C) 2005 Free Software Foundation, Inc. 
$ cat hm.sh 
p() { 
    printf "%-11s : f=%1s : " "$*" "$f" 
    eval printf \'%1s :\\n\' "[email protected]" 
} 

p '$f' 
p '${!f[@]}' 
p '${!f[@]:-b}' 
echo "echo: ${!f[@]:-b} :" 
p '${!f[@]:+b}' 
echo "echo: ${!f[@]:+b} :" 
f=f 
p '$f' 
p '${!f[@]}' 
p '${!f[@]:-b}' 
echo "echo: ${!f[@]:-b} :" 
p '${!f[@]:+b}' 
echo "echo: ${!f[@]:+b} :" 
f=t 
p '$f' 
p '${!f[@]}' 
p '${!f[@]:-b}' 
echo "echo: ${!f[@]:-b} :" 
p '${!f[@]:+b}' 
echo "echo: ${!f[@]:+b} :" 

$ bash hm.sh 
$f   : f= : : 
${!f[@]} : f= : : 
${!f[@]:-b} : f= : b : 
echo: b : 
${!f[@]:+b} : f= : : 
echo: : 
$f   : f=f : f : 
${!f[@]} : f=f : 0 : 
${!f[@]:-b} : f=f : f : 
echo: f : 
${!f[@]:+b} : f=f : b : 
echo: b : 
$f   : f=t : t : 
${!f[@]} : f=t : 0 : 
${!f[@]:-b} : f=t : b : 
echo: b : 
${!f[@]:+b} : f=t : : 
echo: : 

Именно поэтому делать содержания переменных в изменении вопроса, как ${!name[@]:-default} и ${!name[@]:+alt} разложения расширения, когда содержание делать не изменение как расширение ${!name[@]} расширяет?

ответ

3

В синтаксисе ${!f[@]} разложение параметров анализируется как выражение «list the keys», которое является одним из особых исключений из правила, которое {! вводит уровень косвенности. Синтаксис ${!f[@]:-b} не соответствует этому шаблону (потому что она заканчивается :-b), так что !является истолкован как косвенной ссылка, и, следовательно, это переменное, имя является значением f которое проходит проверку по умолчанию модификатор значения.

Интересный вопрос: «Что делает [@] в этом выражении?» Кажется, что он изменяет f, который ничего не делает, когда f является скаляром, но создает недопустимое имя, когда f является массивом из нескольких элементов; в этом случае, по-видимому, происходит замена значения по умолчанию.

Мое лучшее предположение, что это недокументированный и, возможно, непреднамеренный угловой случай расширения параметра.

+0

А, вы предполагаете, что оболочка выполняет '$ {! F [@]: - b}' -> '$ {f [@]: - b}' и '$ {! F [@]: -b} '->' $ {t [@]: - b} ', а затем (эффективно) игнорирование' [@] 'as' $ {not_array [@]} 'такое же, как' $ {not_array} ' а затем увидеть '$ {f: -b}' или '$ {t: -b}'? Это не первый раз, когда я пожелал поэтапного расширения отладки в оболочке. –

+0

@EtanReisner: Если в вашем тесте вы устанавливаете 'f = t t = u', что вы видите? Но я не знаю, что '[@]' игнорируется, точно.Кажется, что это игнорируется только в том случае, когда 'f' является скаляром. Afaics, если f является массивом, даже одного элемента, косвенная неудача и значение по умолчанию заменяется. – rici

+0

't',' 0', 'u',' b' для четырех расширений, которые соответствуют вашим объяснениям. И да, я специально говорил о скалярном/не-массивом случае для '[@]' игнорируется (что я также не понимаю, но это другая проблема). Случай массива - это расширение нормальных значений (которое соответствует тому, что вы видели и чего я ожидаю). Я не пробовал эту косвенность/расширение с помощью массивов, потому что это было не то, с чем я играл в то время. –

Смежные вопросы