shell脚本中的间接参数替换

时间:2010-12-07 18:55:57

标签: shell scripting posix

我遇到了shell脚本(HP-UX下的POSIX shell,FWIW)的问题。我有一个名为print_arg的函数,我将参数名称传递给$ 1。给定参数的名称,然后我想打印该参数的名称和值。但是,我一直收到错误。以下是我正在尝试做的一个例子:

#!/usr/bin/sh

function print_arg
  {
  # $1 holds the name of the argument to be shown

  arg=$1

  # The following line errors off with
  #   ./test_print.sh[9]: argval=${"$arg"}: The specified substitution is not valid for this command.

  argval=${"$arg"}

  if [[ $argval != '' ]] ; then
    printf "ftp_func: $arg='$argval'\n"
  fi
  }

COMMAND="XYZ"

print_arg "COMMAND"

我试过以我能想到的每一种方式重写违规行。我咨询了当地的神谕。我查看了在线“BASH脚本指南”。我磨了一把“波浪刀”的刀,擦了擦坛,直到它闪闪发光,但后来我发现我们当地的处女供应已经减少到了,就像没什么。 DRAT!

有关如何获取其名称作为参数传递给函数的参数值的任何建议都将得到认可。

4 个答案:

答案 0 :(得分:9)

在bash中(但在其他sh实现中没有),间接是通过以下方式完成的:${!arg}

输入

foo=bar
bar=baz

echo $foo
echo ${!foo}

输出

bar
baz

答案 1 :(得分:7)

您可以使用eval,但如果您使用bash,使用直接间接作为suggested by SiegeX可能会更好。

#!/bin/sh

foo=bar
print_arg () {
    arg=$1
    eval argval=\"\$$arg\"
    echo "$argval"
}
print_arg foo

答案 2 :(得分:1)

这非常好用:

#!/bin/sh
foo=bar

print_arg () {
    local line name value
    set | \
    while read line; do
        name=${line%=*} value=${line#*=\'}
        if [ "$name" = "$1" ]; then
            echo ${value%\'}
        fi
    done
}

print_arg foo

它具有所有POSIX笨拙,在Bash中会有很多分类,但是再次,你不需要它,因为你有${!}。这个 - 如果它证明是可靠的 - 将具有仅使用内置和eval 的优势。如果我使用外部命令构造此函数,则必须是sed。将消除对读取循环和替换的需要。请注意,在没有评估的情况下要求POSIX的间接性,必须用笨拙的方式支付!所以不要打败我!

答案 3 :(得分:1)

尽管答案已经被接受,但这是另一种方法,适用于需要保留换行符和特殊字符(如Escape(\033))的人:将变量存储在 base64 < /强>

你需要: bc,wc,echo,tail,tr,uuencode,uudecode

实施例

#!/bin/sh


#====== Definition =======#
varA="a
b
c"
# uuencode the variable
varB="`echo "$varA" | uuencode -m -`"
# Skip the first line of the uuencode output.
varB="`NUM=\`(echo "$varB"|wc -l|tr -d "\n"; echo -1)|bc \`; echo "$varB" | tail -n $NUM)`"


#====== Access =======#

namevar1=varB
namevar2=varA

echo simple eval:
eval "echo \$$namevar2"
echo simple echo: 
echo $varB
echo precise echo: 
echo "$varB"
echo echo of base64
eval "echo \$$namevar1"
echo echo of base64 - with updated newlines
eval "echo \$$namevar1 | tr ' ' '\n'"
echo echo of un-based, using sh instead of eval (but could be made with eval, too)
export $namevar1
sh -c "(echo 'begin-base64 644 -'; echo \$$namevar1 | tr ' ' '\n' )|uudecode"

结果

simple eval:
a b c
simple echo:
YQpiCmMK ====
precise echo:
YQpiCmMK
====
echo of base64
YQpiCmMK ====
echo of base64 - with updated newlines
YQpiCmMK
====
echo of un-based, using sh instead of eval (but could be made with eval, too)
a
b
c

替代

您也可以使用set命令并解析它的输出;因此,在访问变量之前,您不需要以特殊方式处理变量。