【问题标题】:How to get the index of an element in an array using a bash function如何使用bash函数获取数组中元素的索引
【发布时间】:2020-04-02 16:14:00
【问题描述】:

这是我的代码:

function get_index() {
 my_array="$1"
 value="$2"
 for i in "${!my_array[@]}"; do
   if [[ "${my_array[$i]}" = "${value}" ]]; then
       echo "was found"
       echo "${i}";
   fi
 done
 return -1
}

echo "index test"
get_index "${cut_pages[@]}" 5
index=$?
echo $index

数组包括25 它必须返回 1,但它返回 255

有什么问题?

【问题讨论】:

  • my_array 是一个字符串,而不是一个数组。
  • 函数中,$1 == ${cut_pages[0]}$2 == ${cut_pages[1]}等。
  • $? 包含return 语句中使用的值,而不是函数的输出。您需要使用index=$(get_index ...) 来获取输出。

标签: arrays linux bash


【解决方案1】:

您可以使用对数组的名称引用,而不是将整个数组作为单独的参数传递:

function get_index() {
  local -n my_array=$1 # use -n for a reference to the array
  for i in "${!my_array[@]}"; do
    if [[ ${my_array[i]} = $2 ]]; then
      printf '%s\n' "$i"
      return
    fi
  done
  return 1
}

cut_pages=( 1 2 3 4 5 )
index=$(get_index cut_pages 5) && echo "index=$index"

【讨论】:

    【解决方案2】:

    您不能将数组作为单个参数传递给函数。当您编写 "${cut_pages[@]}" 时,它会将数组传播到函数的单独参数中。

    我已更改函数以将要搜索的值作为第一个参数,并且数组是所有其余参数。将其分配给 value 后,shift 命令将其从参数列表中删除,然后我遍历 "$@" 以处理剩余的参数。

    您也没有正确获得函数的结果。 $? 包含return 语句中的状态代码。要获得函数的回声,请使用$(...)。我已经删除了echo "was found",所以这不会进入结果。

    #!/bin/bash
    
    function get_index() {
        value="$1"
        shift
        local index=0
        for i in "$@"; do
            if [[ "$i" = "${value}" ]]; then
                echo "${index}";
                return
            fi
            ((index++))
        done
        return 1
    }
    
    echo "index test"
    cut_pages=(2 5)
    if index=$(get_index 5 "${cut_pages[@]}"); then
        echo $index
    fi
    

    【讨论】:

      【解决方案3】:

      扩展其他答案,这里有一些功能可以处理多个索引处的值;并在多个索引处处理多个值,并将结果返回到数组:

      #!/usr/bin/env bash
      
      function get_indexes() {
        local -n my_array="$1" # use -n for a reference to the array
        local -a indx=()
        local -i rc=1
        for i in "${!my_array[@]}"; do
          if [ "${my_array[i]}" = "$2" ]; then
            indx+=("$i")
            rc=0
          fi
        done
        echo "${indx[*]}"
        return $rc
      }
      
      function get_all_indexes() {
        if [ $# -lt 3 ]; then
          printf 'get_all_indexes input_array output_array values...\n' >&2
          return 2
        fi
        local -n input_array="$1" # use -n for a reference to the array
        shift
        local -n output_array="$1"
        shift
        if ! [[ "$(typeset -p "${!output_array}")" =~ ^declare\ -A ]]; then
           printf 'Output array %s must be an associative array!\n' "${!output_array}" >&2
           return 2
        fi
      
        local -i rc=1
        for i in "${!input_array[@]}"; do
          for value; do
            if [ "${input_array[$i]}" = "$value" ]; then
              if [ ${#output_array[$value]} -eq 0 ]; then
                output_array[$value]="$i"
              else
                printf -v output_array[$value] $'%s\3%s' "${output_array[$value]}" "$i"
              fi
              rc=0
            fi
          done
        done
        return $rc
      }
      
      echo "Testing multi indexes single value"
      declare -a cut_pages=([3]=2 [7]=5 [1]=3 [0]=5)
      typeset -p cut_pages
      if indexes=$(get_indexes cut_pages 5); then
        echo "found 5 at indexes:"
        echo "$indexes"
      fi
      
      printf "\n\nTesting multi indexes multiple values output to array\n"
      declare -A out_arr=()
      declare -A in_arr=(
       ["first"]="hello"
       ["second"]="world"
       ["third"]="hello"
       ["fourth"]="you"
      )
      typeset -p in_arr
      
      if get_all_indexes in_arr out_arr "hello" "world" "you"; then
        for k in "${!out_arr[@]}"; do
          printf 'Found %q at indexes:\n' "$k"
          IFS=$'\3' read -r -a indexes <<<"${out_arr[$k]}"
          printf '%q\n' "${indexes[@]}"
        done
      fi
      

      输出结果:

      Testing multi indexes single value
      declare -a cut_pages=([0]="5" [1]="3" [3]="2" [7]="5")
      found 5 at indexes:
      0 7
      
      
      Testing multi indexes multiple values output to array
      declare -A in_arr=([fourth]="you" [third]="hello" [first]="hello" [second]="world" )
      
      Found world at indexes:
      second
      Found you at indexes:
      fourth
      Found hello at indexes:
      third
      first
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-04-22
        • 1970-01-01
        • 2022-01-12
        • 1970-01-01
        • 2021-08-17
        相关资源
        最近更新 更多