Нам нужно сравнить (и различать):
"${Var}" # Plain variable
"${!Var}" # Indirect expansion
"${!Var@}" # Prefix expansion
"${!Var[@]}" # Array keys expansion
"${Var[@]}" # Plain array expansion
Существуют также расширения *
, которые очень похожи, но имеют небольшую разницу.
Пример косвенного обращения:
$ varname=var_one
$ var_one=a-value
$ echo "${varname}"
var_one
$ echo "${!varname} and ${var_one}"
a-value and a-value
Пример для префикса:
$ head_one=foo
$ head_two=bar
$ printf '<%s> ' "${!head@}"
<head_one> <head_two>
$ printf '<%s> ' "${!head*}"
<head_one head_two>
Обратите внимание, что переменные склеиваются вместе первым символом IFS, который по умолчанию является пробелом (поскольку IFS - это Пробел Вкладка NewLine по умолчанию).
Пример массива (нет! Используется) для демонстрации небольшого (но важного) различия между @
и *
:
$ Array[1]=This
$ Array[2]=is
$ Array[3]=a
$ Array[4]=simple
$ Array[5]=test.
$ printf '<%s> ' "${Array[@]}"
<This> <is> <a> <simple> <test.>
$ printf '<%s> ' "${Array[*]}"
<This is a simple test.>
Тот же комментарий о IFS подать заявку здесь.
Обратите внимание, что я не присвоил массиву индекс 0 (специально).
Обратите внимание, что более простой способ назначить массив:
$ Array=( "" This is a simple test.)
Но здесь должен использоваться индекс 0, и я использовал пустое значение (которое не то же самое, что неустановленное значение, как указано выше).
Для этого простой индексированный массив (с числами) не так уж интересен:
$ Array=( "" A simple example of an array.)
$ printf '<%s> ' "${!Array[@]}"
<0> <1> <2> <3> <4> <5> <6>
$ printf '<%s> ' "${!Array[*]}"
<0 1 2 3 4 5 6>
Но для ассоциативного массива все становится более интересным
$ unset Array # erase any notion of variable array.
$ declare -A Array # make it associative
$ Array=([foo]=one [bar]=two [baz]=three) # give it values.
$ printf '<%s> ' "${Array[@]}"
<two> <three> <one> # List of values.
$ printf '<%s> ' "${!Array[@]}"
<bar> <baz> <foo> # List of keys
$ printf '<%s> ' "${Array[*]}"
<two three one> # One string of list of values.
$ printf '<%s> ' "${!Array[*]}"
<bar baz foo> # One string of list of keys.
Обратите внимание, что порядок не такой, как при назначении.
Примечание: Все представленные мной варианты использования цитируются "$ {! Array [@]}"
, оба значения без кавычек $ {! Array [@]}
и $ {! Array [*]}
работают точно так же, дают одинаковый результат (в Bash).
Но на них влияет разделение оболочки на значение IFS. И уродливое, всегда проблематичное "расширение пути". Не так уж и полезно в целом. Или, в любом случае, использовать очень осторожно.
Если вам не нужны временные метки, вы можете использовать команду history -s
, чтобы добавить строки в историю bash
.
bash-4.2$ history -s foo
bash-4.2$ history -s this is a command
bash-4.2$ history 3
31 foo
32 this is a command
33 history 3
Вы можете манипулировать своим текстовым файлом, чтобы сгенерировать команды history -s
, а затем source
его.