shell 如果使用函数,则无法从Unix bash数组中提取值

fiei3ece  于 2023-08-07  发布在  Shell
关注(0)|答案(4)|浏览(106)

我正在尝试从bash数组中提取值。如果是下面的代码就可以正常工作-

### stk3.sh 
#!bin/bash
declare -x -A my_ids
my_ids[cat]=100
my_ids[dog]=200
id_key=${1:-cat}  ## setting default
echo "Id key is :${id_key}"
id_no=${my_ids[$id_key]}
echo "Value is ### ${id_no}"

字符串
如果我执行上面的命令,我会得到所需的输出-(将上面的脚本保存在stk3.sh中)

./stk3.sh dog
       Id key is :dog
       Value is ### 200


现在,当我使用函数时,我无法获得所需的输出。在一个脚本(stk1.sh)中定义函数,并调用该函数从另一个脚本(stk2.sh)中的特定键获取值

### stk1.sh
#!/bin/bash
declare -x -A my_ids
function my_ids {
  my_ids[cat]=100
  my_ids[dog]=200
  echo "Length of Array :${#my_ids[*]}"
  echo "*** Now printing the contents of the Array ...."
  for x in "${!my_ids[@]}"
  do
    printf "$x  ${my_ids[$x]} \n"
  done
}
my_ids

function get-value {
  printf "$1\n"
  if [[ -n "$1" ]]
    then
    id_no=${my_ids[$id_key]}
  fi
}


当使用调用函数时,我没有得到想要的结果-这里是我的stk2.sh

### stk2.sh 
#!/bin/bash
 
source stk1.sh
id_key=${1:-cat}  ## setting default
echo "Id key is :${id_key}"
id_no=$(get-value $id_key)
echo "Value is ### ${id_no}"


执行skt2.sh后的输出,正如你所看到的,它没有返回id _no的值,在本例中应该是200:

./stk2.sh dog
Length of Array :2
*** Now printing the contents of the Array ....
dog  200 
cat  100 
Id key is :dog
Value is ### dog

1hdlvixo

1hdlvixo1#

id_no是在get-value()函数调用中设置的,由于您没有将id_no定义为函数的“本地”,因此id_no的新值将自动可用于调用/父进程。
你要做的是调用函数而不试图捕获它的输出,例如:

$ cat stk2.sh 
#!/bin/bash

source stk1.sh
id_key=${1:-cat}  ## setting default
echo "Id key is :${id_key}"
get-value $id_key
echo "Value is ### ${id_no}"

字符串

d7v8vwbk

d7v8vwbk2#

get-value分配id_no的值并输出输入。但是主脚本指定id_no保存get-value的输出,这是您传入的密钥。不是你想要的行为。
试试看

function get-value {
    printf '%s\n' "${my_ids[$1]:?"no such key"}"
}

字符串
如果var为null或未设置,${var:?error-message}将发出错误消息,并生成错误状态。参见https://www.gnu.org/software/bash/manual/bash.html#Shell-Parameter-Expansion
然后主脚本可以有

if ! id_no=$(get-value "$id_key"); then
    echo "try a different key"
    exit 1
fi
do-something-with "$id_no"

axzmvihb

axzmvihb3#

你想做的事情是不可能的。在bash中,你不能返回不是函数退出代码的东西。This answer讨论替代方案。
stk2.sh中的id_no=$(get-value $id_key)行捕获了该命令的所有输出(在子shell中使用$(...)启动该命令),在本例中,该命令由stk1.sh中的printf "$1\n"行确定。
Here是另一个关于bash函数返回值的有见地的讨论。

pxy2qtax

pxy2qtax4#

你的get-value函数...

function get-value {
  printf "$1\n"
  if [[ -n "$1" ]]
    then
    id_no=${my_ids[$id_key]}
  fi
}

字符串
...打印它的第一个参数(“$1”),然后,如果后者非空,则将my_ids[$id_key]的值赋给变量id_no
这就引出了几个问题:
1.为什么你的get-value函数会操作那些没有作为参数传递的变量?get-valuecommand substitution 语句中被调用:它运行在一个子shell中,带有父环境的副本。当然,它 * 将 * 能够访问id_key的值,因为id_key碰巧在stk2.sh中更早定义,但是检查第一个函数参数(“$1”)是否为空有什么用呢?
1.你关于id_no的赋值语句将 * 不 * 反映在父环境中。它只在get-value的子shell运行期间存在。
1.你滥用了命令替换功能$(get-value $id_key)将被替换为在子shell运行期间打印到STDOUT的任何内容。因为你的函数执行printf "$1\n",所以它实际上返回(作为替换字符串)它的第一个参数的值。所以如果id_key是“cat”,则$(get-value $id_key)返回“cat”。
总结一下(假设stk2.sh调用为./stk2.sh dog

id_key=${1:-cat}  ## setting default     id_key is set to "dog"

id_no=$(get-value $id_key)               within subshell:
                                            * print "dog\n"
                                            * id_no=200
                                         back to initial environment:
                                            * id_no="dog"

echo "Value is ### ${id_no}"             prints "Value is ### dog"


简单的建议:

function get-value {
  if [[ -n "$1" ]]
    then
      echo ${my_ids[$1]}
  fi  
}


希望能帮上忙。

相关问题