Как получить индекс элемента в массиве с помощью функции bash - PullRequest
0 голосов
/ 02 апреля 2020

Это мой код:

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

Массив включает в себя 2 и 5 Он должен возвращать 1, но возвращает 255

В чем проблема?

Ответы [ 3 ]

2 голосов
/ 02 апреля 2020

Вы можете использовать ссылку на имя массива вместо передачи всего массива в качестве отдельных аргументов:

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 голосов
/ 02 апреля 2020

Расширяясь на другие ответы, здесь представлены функции для обработки значения в нескольких индексах; и для обработки значений, кратных нескольким индексам, с возвращением результата в массив:

#!/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
2 голосов
/ 02 апреля 2020

Вы не можете передать массив как один аргумент функции. Когда вы пишете "${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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...