获取Bash数组中值的索引

use*_*369 53 arrays indexing bash

我有什么bash

myArray=('red' 'orange' 'green')
Run Code Online (Sandbox Code Playgroud)

我想做点什么

echo ${myArray['green']}
Run Code Online (Sandbox Code Playgroud)

在这种情况下会输出2.这可以实现吗?

Ste*_*lsh 74

这样做:

#!/bin/bash

my_array=(red orange green)
value='green'

for i in "${!my_array[@]}"; do
   if [[ "${my_array[$i]}" = "${value}" ]]; then
       echo "${i}";
   fi
done
Run Code Online (Sandbox Code Playgroud)

显然,如果你把它变成一个函数(例如get_index()) - 你可以把它变成通用的

  • 这不适用于稀疏数组或关联数组。要使其适用于所有类型的数组,请将 C 风格的 for 循环替换为:`for i in "${!my_array[@]}"; 做`。此外,如果您只想找到第一个索引,您可能希望在找到索引时“中断”循环。 (2认同)
  • 您能否解释一下$ !! my_array [@]}中的`!`是什么意思? (2认同)
  • @bodacydo,我想知道“!”也意味着,然后尝试了一下,发现它没有列出数组中的所有值,而是列出了从零开始的索引。 (2认同)
  • `!` 表示返回元素的索引而不是元素的值。 (2认同)

Ola*_*che 29

您必须在使用之前声明您的阵列

declare -A myArray
myArray=([red]=1 [orange]=2 [green]=3)
echo ${myArray['orange']}
Run Code Online (Sandbox Code Playgroud)

  • OP希望索引而不是值。 (4认同)
  • @Dejan 是的,这就是标题。但也要看看问题,看看OP想要实现什么。 (2认同)

che*_*ner 13

不可以.您只能使用整数索引一个简单数组bash.关联数组(在bash4中引入)可以用字符串索引.但是,它们没有提供您要求的反向查找类型,没有特殊构造的关联数组.

$ declare -A myArray
$ myArray=([red]=0 [orange]=1 [green]=2)
$ echo ${myArray[green]}
2
Run Code Online (Sandbox Code Playgroud)


小智 10

还有一个棘手的方法:

echo ${myArray[@]/green//} | cut -d/ -f1 | wc -w | tr -d ' '
Run Code Online (Sandbox Code Playgroud)

你得到2 这里是参考

  • 巧妙的解决方案.唯一的原因我没有将这个更简单的标记为已接受(虽然我赞成它)是因为它更容易出错.虽然[当前接受的答案](http://stackoverflow.com/a/15028821/1661012)在输入无效颜色时将"回显",但此解决方案将输入数组中的元素数加1(所以`3 `,跟随我的示例数组),这可能有点难以调试. (2认同)

srb*_*rbs 6

另一个棘手的台词:

index=$((-1 + 10#0$(IFS=$'\n' echo "${my_array[*]}" | grep --line-number --fixed-strings -- "$value" | cut -f1 -d:)))
Run Code Online (Sandbox Code Playgroud)

特征:

  • 支持带空格的元素
  • -1未找到时返回

注意事项:

  • 要求value非空
  • 难以阅读

按执行顺序分解进行解释:

IFS=$'\n' echo "${my_array[*]}"
Run Code Online (Sandbox Code Playgroud)

将数组扩展分隔符 ( IFS) 设置为新行字符并扩展数组

grep --line-number --fixed-strings -- "$value"
Run Code Online (Sandbox Code Playgroud)

grep 匹配:

  • 显示行号 (--line-number-n)
  • 使用固定字符串(--fixed-strings-F;禁用正则表达式)
  • 允许以-( --)开头的元素

    切-f1-d:

仅提取行号(格式为<line_num>:<matched line>

$((-1 + 10#0$(...)))
Run Code Online (Sandbox Code Playgroud)

减去 1,因为行号的索引为 1,数组的索引为 0

  • 如果$(...)不匹配:

    • 0没有返回任何内容并且使用默认值( 10#0)
  • 如果$(...)匹配:
    • 存在行号 & 前缀为10#0; 即10#02、、、等10#0910#014
    • 前缀10#强制以 10 为基数/十进制数字而不是八进制


使用, &awk代替bash 算术:grepcut

IFS=$'\n'; awk "\$0 == \"${value//\"/\\\"}\" {print NR-1}" <<< "${my_array[*]}"
Run Code Online (Sandbox Code Playgroud)

特征:

  • 支持带空格的元素
  • 支持空元素
  • 在子 shell 中打开的 less 命令

注意事项:

  • 未找到时返回

按执行顺序分解进行解释:

IFS=$'\n' [...] <<< "${my_array[*]}"
Run Code Online (Sandbox Code Playgroud)

将数组扩展分隔符 ( IFS) 设置为新行字符并扩展数组

awk "\$0 == \"${value//\"/\\\"}\" {print NR-1}"
Run Code Online (Sandbox Code Playgroud)

匹配整行并打印 0 索引的行号

  • ${value//\"/\\\"}$value用转义版本替换双引号
  • 由于我们需要变量替换,因此该段的转义量比想要的要多


cmc*_*nty 5

更简洁一点,适用于 Bash 3.x:

my_array=(red orange green)
value='green'

for i in "${!my_array[@]}"; do
   [[ "${my_array[$i]}" = "${value}" ]] && break
done

echo $i
Run Code Online (Sandbox Code Playgroud)