2017-08-08 3 views
2

J'ai un tableau associatif qui agit comme un double tableau habituel.Obtention de la longueur d'une partie d'un tableau associatif (double) dans Bash

La structure est similaire à celle-ci: [[0,1], [0,1,2]]. Code:

declare -A array 
array[0,0]=0 
array[0,1]=1 
array[1,0]=0 
array[1,1]=1 
array[1,2]=2 

Comment puis-je obtenir des longueurs de tableau [0] et tableau [1]? Dans cet exemple: 2 et 3.

Merci.

P.S. J'ai essayé de rechercher des doublons. Sans succès. Et si ce n'est pas clair: je ne connais pas la longueur du tableau.


La réponse a été choisie après un test d'efficacité. Voici exemple de fonction basée sur @ RenaudPacalet de réponse:

function getLength() { 
    local k=$(eval "echo \${!$1[@]}") 
    local re="(\<$2,[0-9])" 
    echo $k | grep -Eo $re | wc -l 
} 

Exemple d'utilisation: getLength array 1 renvoie 3 dans le cas de cette question. Gardez à l'esprit que l'utilisation de $(eval "echo \${!$1[@]}") est beaucoup plus lente que ${!array[@]}.

+0

" qui agit comme si c'était un double tableau habituel "Non, ça ne fonctionne pas, ça * agit toujours comme un tableau associatif. –

+1

echo $ {# array [@]} – py9

+0

@Ignacio Vazquez-Abrams, je veux dire qu'il rappelle de double tableau. Pas d'actes, si vous voulez :) – MOPO3OB

Répondre

0
k=${!array[@]} 
n=0 
re="(\<$n,[0-9]+)" 
echo $k | grep -Eo $re | wc -l 
  1. obtenir les clés de votre tableau,
  2. mis l'index de ligne,
  3. créer une expression régulière pour les clés correspondantes,
  4. filtre les clés à l'aide de l'expression régulière et compter le nombre des matches.

Et répéter avec d'autres index de ligne, si nécessaire. L'expression régulière est un peu difficile. \< est un début de mot (pour éviter cela 10,10 correspond à 0,). $n,[0-9]+ est l'index de ligne actuel, suivi d'une virgule et d'un ou plusieurs chiffres. Les parenthèses englobantes délimitent une sous-expression.

Les options -Eo de grep le mettent en mode d'expression régulière étendu et séparent les chaînes correspondantes avec de nouvelles lignes, de sorte que wc -l peut les compter.

+0

cela fonctionne seulement sans * dans RegEx. La version de grep 2.5.1. – MOPO3OB

+0

Cette implémentation est vraiment regrettable. Considérez si vous avez un astérisque littéral comme une clé - le 'echo *' va émettre une liste de noms de fichiers. Et 'grep -o' est un GNUism, non garanti par [la spécification POSIX pour' grep'] (http://pubs.opengroup.org/onlinepubs/9699919799/utilities/grep.html). –

+0

@CharlesDuffy pour le cas d'exemple dans la question, c'est juste correct. Mais j'ai compris ce que tu veux dire. Appréciez les deux réponses. C'est pourquoi j'ai mis à jour la question en spécifiant le critère de choix de la réponse. – MOPO3OB

3

Vous devrez parcourir les clés du tableau et compter ceux que vous aimez: il n'y a pas de syntaxe pour quelque chose comme ${array[0,*])

n0=0 
n1=0 
for key in "${!array[@]}"; do 
    [[ $key == 0,* ]] && ((n0++)) 
    [[ $key == 1,* ]] && ((n1++)) 
done 
echo $n0 
echo $n1 

Ou, utilisez un tableau pour tenir le compte de tous les « premier niveau "indices

n=() 
for key in "${!array[@]}"; do ((n[${key%%,*}]++)); done 
# then, print out the counts 
for ind in "${!n[@]}"; do printf "%s\t%s\n" $ind "${n[$ind]}"; done