Имена динамических переменных в Bash

Я смущен сценарием bash.

у меня есть следующий код:

function grep_search() {
    magic_way_to_define_magic_variable_=`ls | tail -1`
    echo $magic_variable_
}

Я хочу иметь возможность создать имя переменной, содержащее первый аргумент команды и несущее значение, например, последней строки ls.

Итак, чтобы проиллюстрировать, что я хочу:

$ ls | tail -1
stack-overflow.txt

$ grep_search() open_box
stack-overflow.txt

Итак, как я должен определить/объявление $magic_way_to_define_magic_variable_ и как я должен назвать это в сценарии?

Я пробовал eval, ${...}, $${...}, но я все еще смущенный.

9 ответов


используйте ассоциативный массив с именами команд в качестве ключей.

# Requires bash 4, though
declare -A magic_variable=()

function grep_search() {
    magic_variable[]=$( ls | tail -1 )
    echo ${magic_variable[]}
}

если вы не можете использовать ассоциативные массивы (например, необходимо поддерживать bash 3), Вы можете использовать declare для создания имен динамических переменных:

declare "magic_variable_=$(ls | tail -1)"

и используйте косвенное расширение параметра для доступа к значению.

var="magic_variable_"
echo "${!var}"

См. BashFAQ:Indirection-оценка косвенных / ссылочных переменных.


Я искал лучший способ сделать это в последнее время. Ассоциативный массив казался мне излишним. Посмотрите, что я нашел:

suffix=bzz
declare prefix_$suffix=mystr

...и...

varname=prefix_$suffix
echo ${!varname}

пример ниже возвращает значение $name_of_var

var=name_of_var
echo $(eval echo "$$var")

Это должно работать:

function grep_search() {
    declare magic_variable_="$(ls | tail -1)"
    echo "$(tmpvar=magic_variable_ && echo ${!tmpvar})"
}
grep_search var  # calling grep_search with argument "var"

для индексированных массивов, вы можете ссылаться на них, как так:

foo=(a b c)
bar=(d e f)

for arr_var in 'foo' 'bar'; do
    declare -a 'arr=("${'"$arr_var"'[@]}")'
    # do something with $arr
    echo "$$arr_var contains:"
    for char in "${arr[@]}"; do
        echo "$char"
    done
done

ассоциативные массивы могут ссылаться аналогично, но нуждаются в -A переключатель declare вместо -a.


Вау, большая часть синтаксиса ужасна! Вот одно решение с более простым синтаксисом, если вам нужно косвенно ссылаться на массивы:

#!/bin/bash

foo_1=("fff" "ddd") ;
foo_2=("ggg" "ccc") ;

for i in 1 2 ;
do
    eval mine=( ${foo_$i[@]} ) ;
    echo ${mine[@]} ;
done ;

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


Я хочу иметь возможность создать имя переменной, содержащее первый аргумент команды

:

#!/usr/bin/env bash
function grep_search() {
  eval =$(ls | tail -1)
}

по состоянию на BashFAQ/006, вы можете использовать read С здесь синтаксис строки для распределения косвенных переменных:

function grep_search() {
  read "" <<<$(ls | tail -1);
}

использование:

$ grep_search open_box
$ echo $open_box
stack-overflow.txt

на , например:

varname=${prefix}_suffix