Dynamic variable names in Bash

后端 未结 14 1992
清酒与你
清酒与你 2020-11-21 05:38

I am confused about a bash script.

I have the following code:

function grep_search() {
    magic_way_to_define_magic_variable_$1=`ls | tail -1`
    e         


        
相关标签:
14条回答
  • 2020-11-21 06:18

    Use declare

    There is no need on using prefixes like on other answers, neither arrays. Use just declare, double quotes, and parameter expansion.

    I often use the following trick to parse argument lists contanining one to n arguments formatted as key=value otherkey=othervalue etc=etc, Like:

    # brace expansion just to exemplify
    for variable in {one=foo,two=bar,ninja=tip}
    do
      declare "${variable%=*}=${variable#*=}"
    done
    echo $one $two $ninja 
    # foo bar tip
    

    But expanding the argv list like

    for v in "$@"; do declare "${v%=*}=${v#*=}"; done
    

    Extra tips

    # parse argv's leading key=value parameters
    for v in "$@"; do
      case "$v" in ?*=?*) declare "${v%=*}=${v#*=}";; *) break;; esac
    done
    # consume argv's leading key=value parameters
    while (( $# )); do
      case "$v" in ?*=?*) declare "${v%=*}=${v#*=}";; *) break;; esac
      shift
    done
    
    0 讨论(0)
  • 2020-11-21 06:18

    For indexed arrays, you can reference them like so:

    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
    

    Associative arrays can be referenced similarly but need the -A switch on declare instead of -a.

    0 讨论(0)
  • 2020-11-21 06:18

    I want to be able to create a variable name containing the first argument of the command

    script.sh file:

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

    Test:

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

    As per help eval:

    Execute arguments as a shell command.


    You may also use Bash ${!var} indirect expansion, as already mentioned, however it doesn't support retrieving of array indices.


    For further read or examples, check BashFAQ/006 about Indirection.

    We are not aware of any trick that can duplicate that functionality in POSIX or Bourne shells without eval, which can be difficult to do securely. So, consider this a use at your own risk hack.

    However, you should re-consider using indirection as per the following notes.

    Normally, in bash scripting, you won't need indirect references at all. Generally, people look at this for a solution when they don't understand or know about Bash Arrays or haven't fully considered other Bash features such as functions.

    Putting variable names or any other bash syntax inside parameters is frequently done incorrectly and in inappropriate situations to solve problems that have better solutions. It violates the separation between code and data, and as such puts you on a slippery slope toward bugs and security issues. Indirection can make your code less transparent and harder to follow.

    0 讨论(0)
  • 2020-11-21 06:21

    This should work:

    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"
    
    0 讨论(0)
  • 2020-11-21 06:22

    This will work too

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

    In your case

    eval final_val='$'magic_way_to_define_magic_variable_"$1"
    echo $final_val
    
    0 讨论(0)
  • 2020-11-21 06:24

    An extra method that doesn't rely on which shell/bash version you have is by using envsubst. For example:

    newvar=$(echo '$magic_variable_'"${dynamic_part}" | envsubst)
    
    0 讨论(0)
提交回复
热议问题