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

Я не совсем понимаю сценарий bash.

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

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

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

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

$ ls | tail -1
stack-overflow.txt

$ grep_search() open_box
stack-overflow.txt

Итак, как мне определить /объявить $magic_way_to_define_magic_variable_$1 и как мне вызвать его в скрипте?

Я пробовал eval, ${...}, \$${...}, но я все еще в замешательстве.

101 голос | спросил Konstantinos 15 Mayam13 2013, 01:22:48

10 ответов


0

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

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

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

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

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

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

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

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

ответил chepner 15 Mayam13 2013, 01:43:30
0

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

suffix=bzz
declare prefix_$suffix=mystr

... а потом ...

varname=prefix_$suffix
echo ${!varname}
ответил Yorik.sar 8 PM00000030000000831 2013, 15:00:08
0

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

var=name_of_var
echo $(eval echo "\$$var")
ответил meow meow 17 +03002017-10-17T16:45:19+03:00312017bEurope/MoscowTue, 17 Oct 2017 16:45:19 +0300 2017, 16:45:19
0

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

function grep_search() {
    declare magic_variable_$1="$(ls | tail -1)"
    echo "$(tmpvar=magic_variable_$1 && echo ${!tmpvar})"
}
grep_search var  # calling grep_search with argument "var"
ответил Jahid 12 J000000Sunday15 2015, 16:52:58
0

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

#!/bin/bash

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

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

Для более простых случаев использования я рекомендую описан в Расширенном руководстве по написанию сценариев .

ответил ingyhere 5 Jam1000000amThu, 05 Jan 2017 05:14:54 +030017 2017, 05:14:54
0

Это тоже будет работать

my_country_code="green"
x="country"

eval z='$'my_"$x"_code
echo $z                 ## o/p: green

В вашем случае

eval final_val='$'magic_way_to_define_magic_variable_"$1"
echo $final_val
ответил k_vishwanath 19 +03002018-10-19T12:38:58+03:00312018bEurope/MoscowFri, 19 Oct 2018 12:38:58 +0300 2018, 12:38:58
0

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

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.

ответил Walf 20 J000000Thursday17 2017, 07:30:24
0
  

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

script.sh файл:

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

Тест:

$ source script.sh
$ grep_search open_box
$ echo $open_box
script.sh

Согласно help eval:

  

Выполнить аргументы как команду оболочки.


Вы также можете использовать косвенное расширение Bash ${!var}, как уже упоминалось, однако оно не поддерживает получение индексов массива.


Дополнительную информацию или примеры можно найти в разделе BashFAQ /006 об косвенном обращении . р>

  

Нам неизвестны какие-либо хитрости, которые могут дублировать эту функциональность в оболочках POSIX или Bourne без eval, что может быть трудно сделать надежно. Таким образом, используйте это на свой страх и риск .

Тем не менее, вам следует повторно рассмотреть возможность использования косвенного обращения согласно следующим примечаниям.

  

Обычно в сценариях bash вам вообще не нужны косвенные ссылки. Обычно люди ищут это решение, когда они не понимают или не знают о массивах Bash или еще не полностью рассмотрели другие функции Bash, такие как функции.

     

Помещение имен переменных или любого другого синтаксиса bash внутри параметров часто выполняется неправильно и в неподходящих ситуациях для решения проблем, которые имеют лучшие решения. Это нарушает разделение кода и данных и, как таковое, ставит вас на скользкий путь к ошибкам и проблемам безопасности. Непрямость может сделать ваш код менее прозрачным и трудным для отслеживания.

ответил kenorb 14 AMpSat, 14 Apr 2018 03:50:51 +030050Saturday 2018, 03:50:51
0

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

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

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

$ grep_search open_box
$ echo $open_box
stack-overflow.txt
ответил kenorb 14 AMpSat, 14 Apr 2018 04:04:49 +030004Saturday 2018, 04:04:49
0

для формата varname=$prefix_suffix, просто используйте:

varname=${prefix}_suffix
ответил Monika Bhadauria 13 Jpm1000000pmTue, 13 Jan 2015 12:28:53 +030015 2015, 12:28:53

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

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132