【问题标题】:Passing associative array as argument with Bash [duplicate]将关联数组作为参数传递给 Bash [重复]
【发布时间】:2013-07-07 14:28:41
【问题描述】:

将关联数组作为参数传递给函数以避免重复遍历大量关联数组的最佳方法是什么?这样我就可以为函数提供我选择的任何数组来打印。这是我所拥有的:

# Snippet

declare -A weapons=(
  ['Straight Sword']=75
  ['Tainted Dagger']=54
  ['Imperial Sword']=90
  ['Edged Shuriken']=25
)

print_weapons() {
  for i in "${!weapons[@]}"; do
    printf "%s\t%d\n" "$i" "${weapons[$i]}"
  done
}

print_weapons

【问题讨论】:

标签: linux bash shell


【解决方案1】:

您可以使用local -n 作为参考

 declare -A weapons=(
 ['Straight Sword']=75
 ['Tainted Dagger']=54
 ['Imperial Sword']=90
 ['Edged Shuriken']=25
 )
 
 print_weapons() {
     local -n array=$1
     for i in "${!array[@]}"; do
         printf "%s\t%d\n" "$i" "${array[$i]}"
     done
 }
 
 print_weapons weapons

【讨论】:

  • local -n 选项在 GNU bash 版本 4.2.46(1)-release (x86_64-redhat-linux-gnu) 上不起作用:local: -n: invalid option
  • @Drew:它是在 4.3 中添加的;请参阅tiswww.case.edu/php/chet/bash/NEWS(它没有明确列出local,但local 处理与declare 相同的类型)4.3 于2014-02 发布,尽管发行版不会立即获取新版本
  • local -n - 太神奇了。
【解决方案2】:

我认为您不能将关联数组作为参数传递给函数。不过,您可以使用以下技巧来解决此问题:

#!/bin/bash

declare -A weapons=(
  ['Straight Sword']=75
  ['Tainted Dagger']=54
  ['Imperial Sword']=90
  ['Edged Shuriken']=25
)

function print_array {
    eval "declare -A arg_array="${1#*=}
    for i in "${!arg_array[@]}"; do
       printf "%s\t%s\n" "$i ==> ${arg_array[$i]}"
    done
}

print_array "$(declare -p weapons)" 

输出

Imperial Sword ==> 90   
Tainted Dagger ==> 54   
Edged Shuriken ==> 25   
Straight Sword ==> 75   

【讨论】:

  • 这是我通过一篇文章看到的,这可能是最好的选择。非常感谢您的帮助!
  • 看起来这是从stackoverflow.com/a/8879444/813602 复制(然后稍作编辑)的;请注意,在 ${1#*=} 周围扩展双引号可修复空格问题(如原始答案中所述)。
【解决方案3】:

variable indirection 与常规数组一起使用已经够难看的了,使用关联数组很困难——我没有找到遍历键的方法。

我想知道您是否只需要declare -p

print_array() { declare -p $1; }
print_array weapons
declare -A weapons='(["Imperial Sword"]="90" ["Tainted Dagger"]="54" ["Edged Shuriken"]="25" ["Straight Sword"]="75" )'

或者,更漂亮:

print_array() { declare -p $1 | sed 's/[[)]/\n&/g'; }
print_array weapons
declare -A weapons='(
["Imperial Sword"]="90" 
["Tainted Dagger"]="54" 
["Edged Shuriken"]="25" 
["Straight Sword"]="75" 
)'

【讨论】:

  • 我知道我不会发疯,这对我来说是一个艰难的过程。你能解释一下 sed 发生了什么吗?
  • @Dford.py sed 将在看到[( 字符时附加一个换行符。 & 将匹配 [( 插入新行。
  • 啊,我明白了.. 我将不得不参考我的 sed 手册并选择更多的正则表达式。
  • 有没有办法在没有大括号、方括号和引号的情况下打印它?换句话说,就像@JS웃 一样打印
  • @Dford.py 取决于您希望看到的输出,您可以将其通过管道传送到另一个 sed 类似:declare -p weapons | sed 's/[[)]/\n&/g' | sed 's/[[:punct:]]/ /g
【解决方案4】:
#!/bin/bash

   declare -A dict
   
   dict=(
    [ke]="va"
    [ys]="lu"
    [ye]="es" 
   ) 
   
   fun() {
     for i in $@; do
       echo $i
     done
    }
   
   fun ${dict[@]} 

# ||${dict[key]} || ${!dict[@]} || ${dict[$1]} || ${dict[@]}

【讨论】:

  • 这不会将数组键传递给函数。
  • ...这是您可以毫无问题地传递密钥的选项:我添加评论
  • 样本对我有用。即fun ${dict[ke]} 产生输出va。我想如果你想将它用作fun ke,那么你必须以某种方式将数组的名称传达给函数,或者使用可以硬编码的“定义明确”的数组名称(但这很难看,我猜)。祝大家好运。
  • 什么意思? @shellter
  • 我同意你的帖子 ;-? ...但我添加了一些用户可能很懒惰并希望只传递关键文本的评论,即fun ke 以获取返回的值va。但如果这是他们的目标,他们将不得不增强你的功能。祝大家好运!
猜你喜欢
  • 2023-04-03
  • 1970-01-01
  • 2014-01-10
  • 1970-01-01
  • 2011-10-13
  • 2017-09-26
  • 1970-01-01
  • 2018-08-01
  • 1970-01-01
相关资源
最近更新 更多