Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/opencv/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Arrays 获取Bash数组中值的索引_Arrays_Bash_Indexing - Fatal编程技术网

Arrays 获取Bash数组中值的索引

Arrays 获取Bash数组中值的索引,arrays,bash,indexing,Arrays,Bash,Indexing,我在bash中有类似的东西 myArray=('red' 'orange' 'green') 我想做一些类似的事情 echo ${myArray['green']} 在这种情况下,将输出2。这是可以实现的吗?否。您只能在bash中使用整数对简单数组进行索引。关联数组(在bash4中引入)可以通过字符串进行索引。但是,如果没有特殊构造的关联数组,它们不会提供您所要求的反向查找类型 $ declare -A myArray $ myArray=([red]=0 [orange]=1 [green

我在
bash
中有类似的东西

myArray=('red' 'orange' 'green')
我想做一些类似的事情

echo ${myArray['green']}

在这种情况下,将输出
2
。这是可以实现的吗?

否。您只能在
bash
中使用整数对简单数组进行索引。关联数组(在
bash
4中引入)可以通过字符串进行索引。但是,如果没有特殊构造的关联数组,它们不会提供您所要求的反向查找类型

$ declare -A myArray
$ myArray=([red]=0 [orange]=1 [green]=2)
$ echo ${myArray[green]}
2
这可以做到:

#!/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

显然,如果将其转换为函数(例如get_index()),则可以将其设置为通用的

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

还有一个棘手的方法:

echo ${myArray[@]/green//} | cut -d/ -f1 | wc -w | tr -d ' '
你得到2分 我喜欢这个解决方案:

let "n=(`echo ${myArray[@]} | tr -s " " "\n" | grep -n "green" | cut -d":" -f 1`)-1"
my_array=(red orange green)
echo ${my_array[*]} | tr ' ' '\n' | awk '/green/ {print NR-1}'

变量n将包含结果

这只是另一种初始化关联数组的方法,如切普纳所示。 不要忘记,您需要显式地
声明
或使用
-A
属性设置关联数组

i=0; declare -A myArray=( [red]=$((i++)) [orange]=$((i++)) [green]=$((i++)) )
echo ${myArray[green]}
2
这样就不需要硬编码值,并且不太可能得到重复的值

如果要添加很多值,那么将它们放在单独的行中可能会有所帮助

i=0; declare -A myArray; 
myArray+=( [red]=$((i++)) )
myArray+=( [orange]=$((i++)) )
myArray+=( [green]=$((i++)) )
echo ${myArray[green]}
2
假设你想要一个数字和小写字母的数组(例如:用于菜单选择),你也可以这样做

declare -a mKeys_1=( {{0..9},{a..z}} );
i=0; declare -A mKeys_1_Lookup; eval mKeys_1_Lookup[{{0..9},{a..z}}]="$((i++))";
如果你然后跑

echo "${mKeys_1[15]}"
f
echo "${mKeys_1_Lookup[f]}"
15

这可能只适用于阵列

my_array=(red orange green)
echo "$(printf "%s\n" "${my_array[@]}")" | grep -n '^orange$' | sed 's/:orange//'
输出:

2
如果要在tsv文件中查找头索引

head -n 1 tsv_filename | sed 's/\t/\n/g' | grep -n '^header_name$' | sed 's/:header_name//g'
在zsh中,您可以执行以下操作

xs=( foo bar qux )
echo ${xs[(ie)bar]}

请参阅zshparam(1)小节下标标志,它更简洁一些,在Bash 3.x中可用:

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

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

echo $i

另一个棘手的问题是:

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

  • 支持带有空格的图元
  • 未找到时返回
    -1
注意事项:

  • 要求
    为非空
  • 难懂

按执行顺序分解说明:

IFS=$'\n' echo "${my_array[*]}"
IFS=$'\n' [...] <<< "${my_array[*]}"
将数组扩展分隔符(
IFS
)设置为新行字符并扩展数组

grep --line-number --fixed-strings -- "$value"
awk "\$0 == \"${value//\"/\\\"}\" {print NR-1}"
格雷普比赛:

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

    切割-f1-d:

仅提取行号(格式为

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

  • 如果
    $(…)
    不匹配:

    • 不返回任何内容&使用默认值
      0
      10#0
  • 如果
    $(…)
    匹配:
    • 存在行号&前缀为
      10#0
      ;i、 e.
      10#02
      10#09
      10#014
      ,等等
    • 10 #
      前缀强制使用10进制/十进制数字,而不是八进制数字


使用
awk
代替
grep
cut
&bash算法:

IFS=$'\n'; awk "\$0 == \"${value//\"/\\\"}\" {print NR-1}" <<< "${my_array[*]}"
将数组扩展分隔符(
IFS
)设置为新行字符并扩展数组

grep --line-number --fixed-strings -- "$value"
awk "\$0 == \"${value//\"/\\\"}\" {print NR-1}"
匹配整行并打印0索引行号

  • ${value/\“/\\\”}
    用转义版本替换
    $value
    中的双引号
  • 因为我们需要变量替换,所以这个段的转义比我们想要的要多
    • 简单解决方案:

      let "n=(`echo ${myArray[@]} | tr -s " " "\n" | grep -n "green" | cut -d":" -f 1`)-1"
      
      my_array=(red orange green)
      echo ${my_array[*]} | tr ' ' '\n' | awk '/green/ {print NR-1}'
      

      这将输出查询的基于0的数组索引(此处为“橙色”)

      echo$($(printf“%s\n”“${myArray[@]}”sed-n'/^orange$/{=;q}')-1))
      
      如果查询未在数组中出现,则上述输出
      -1

      如果查询在数组中多次出现,则上面的输出查询第一次出现的索引


      由于该解决方案调用了sed,我怀疑它能否在效率上与该线程中的一些纯bash解决方案竞争。

      这展示了一些返回数组成员索引的方法。 数组对第一个和最后一个索引使用不适用的值, 提供从1开始的索引,并提供限制

      while循环是一种有趣的迭代方法, 为了生成数组值的索引, 循环体仅包含一个用于null操作的冒号。 重要的是迭代i直到匹配, 或者超过可能的匹配项

      函数indexof()将文本值转换为索引。 如果某个值不匹配,则函数返回一个错误代码,该错误代码可能是 在测试中用于执行错误处理。 与数组不匹配的输入值将超过范围限制
      (-gt,-lt)
      测试

      有一个测试(主代码)循环好/坏的值,前3行被注释掉,但尝试一些变化以查看有趣的结果(
      第1、3或2、3或4行
      )。我包含了一些考虑错误条件的代码,因为它可能很有用

      最后一行代码使用已知的良好值“green”调用函数indexof,该值将回显索引值

      indexof(){
        local s i;
      
        #   0    1   2     3    4
        s=( @@@ red green blue @o@ )
      
        while [ ${s[i++]} != $1 ] && [ $i -lt ${#s[@]} ]; do :; done
      
        [ $i -gt 1 ] && [ $i -lt ${#s[@]} ] || return
      
        let i--
      
        echo $i
      };# end function indexof
      
      # --- main code ---
      echo -e \\033c
      echo 'Testing good and bad variables:'
      for x in @@@ red pot green blue frog bob @o@;
      do
        #v=$(indexof $x) || break
        #v=$(indexof $x) || continue
        #echo $v
        v=$(indexof $x) && echo -e "$x:\t ok" || echo -e "$x:\t unmatched"
      done 
      
      echo -e '\nShow the index of array member green:'
      indexof green
      

      我自己也想要类似的东西,避免循环,想出了

      myArray=('red' 'orange' 'green')
      declare -p myArray | sed -n "s,.*\[\([^]]*\)\]=\"green\".*,\1,p"
      
      。。。如果找不到元素,stdout就不会被污染

      $ myArray=('red' 'orange' 'green')
      $ declare -p myArray | sed -n "s,.*\[\([^]]*\)\]=\"green\".*,\1,p"
      2
      
      $ declare -p myArray | sed -n "s,.*\[\([^]]*\)\]=\"gren\".*,\1,p"
      $
      

      之后,我在谷歌上搜索,发现了这个问题,并想与大家分享;)

      我的第一个建议是使用python而不是bash编写脚本。一旦我开始这么做,我就再也不回头了。谢谢你,我知道我可以用python字典轻松地做到这一点,但这不是我想要的。这不适用于稀疏数组或关联数组。要使其适用于所有类型的数组,请将C样式的for循环替换为:“${!my_array[@]}”中的i的
      ;执行
      。另外,如果您只想找到第一个索引,那么如果找到了索引,您可能需要
      中断
      循环。请您解释一下
      是什么
      ${!我的数组[@]}
      ?@bodacydo中的意思,我想知道
      的意思也是,然后尝试了一下,发现它没有列出数组中的所有值,而是