L'index d'une valeur dans un tableau Bash

J'ai quelque chose dans bash comme

myArray=('red' 'orange' 'green')

Et je voudrais faire quelque chose comme

echo ${myArray['green']}

Qui dans ce cas produirait 2. Est-ce réalisable?

34
demandé sur Mateusz Piotrowski 2013-02-22 20:17:13

9 réponses

Cela va le faire:

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

Évidemment, si vous transformez cela en une fonction (par exemple get_index ()) - vous pouvez le rendre Générique

53
répondu Steve Walsh 2015-06-22 16:28:38

, Vous devez déclarer votre tableau avant de l'utiliser avec

declare -A myArray
myArray=([red]=1 [orange]=2 [green]=3)
echo ${myArray['orange']}
23
répondu Olaf Dietsche 2013-02-22 16:32:01

Non. Vous ne pouvez indexer qu'un tableau simple avec un entier dans bash. Les tableaux associatifs (introduits dans bash 4) peuvent être indexés par des chaînes. Ils ne prévoient cependant pas le type de recherche inversée que vous demandez, sans un tableau associatif spécialement construit.

$ declare -A myArray
$ myArray=([red]=0 [orange]=1 [green]=2)
$ echo ${myArray[green]}
2
9
répondu chepner 2017-06-27 20:44:49

Il y a aussi une façon délicate:

echo ${myArray[@]/green//} | cut -d/ -f1 | wc -w | tr -d ' '

Et vous obtenez 2 Voici les références

7
répondu PiotrO 2017-03-20 10:04:24

C'est juste une autre façon d'initialiser un tableau associatif comme chepner l'a montré. N'oubliez pas que vous devez explicitement declare ou taper un tableau associatif avec l'attribut -A.

i=0; declare -A myArray=( [red]=$((i++)) [orange]=$((i++)) [green]=$((i++)) )
echo ${myArray[green]}
2

Cela supprime le besoin de valeurs de code dur et rend peu probable que vous finissiez avec des doublons.

Si vous avez beaucoup de valeurs à ajouter, il peut aider à les mettre sur des lignes séparées.

i=0; declare -A myArray; 
myArray+=( [red]=$((i++)) )
myArray+=( [orange]=$((i++)) )
myArray+=( [green]=$((i++)) )
echo ${myArray[green]}
2

Dites que vous voulez un tableau de chiffres et de lettres minuscules (par exemple: pour une sélection de menu), vous pouvez faites aussi quelque chose comme ça.

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

Si vous exécutez alors

echo "${mKeys_1[15]}"
f
echo "${mKeys_1_Lookup[f]}"
15
2
répondu sbts 2016-11-18 22:51:45

J'aime cette solution:

let "n=(`echo ${myArray[@]} | tr -s " " "\n" | grep -n "green" | cut -d":" -f 1`)-1"

La variable n contiendra le résultat!

1
répondu user3680055 2015-08-13 18:08:54

Cela pourrait juste fonctionner pour les tableaux,

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

Sortie:

2

Si vous voulez trouver l'index d'en-tête dans un fichier tsv,

head -n 1 tsv_filename | sed 's/\t/\n/g' | grep -n '^header_name$' | sed 's/:header_name//g'
1
répondu Manish Sharma 2017-04-12 11:28:47

Dans zsh vous pouvez faire

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

Voir Zshparam (1) sous-section indices

0
répondu yaccz 2017-06-18 04:02:16

Un peu plus concis et fonctionne dans Bash 3.x:

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

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

echo $i
0
répondu cmcginty 2018-05-23 06:39:20