Iterieren Sie in Bash über zwei Arrays gleichzeitig


75

Ich habe zwei Arrays.

array=(
  Vietnam
  Germany
  Argentina
)
array2=(
  Asia
  Europe
  America
)

Ich möchte diese beiden Arrays gleichzeitig durchlaufen, dh einen Befehl für die ersten Elemente der beiden Arrays aufrufen, dann denselben Befehl für die zweiten Elemente aufrufen und so weiter. Pseudocode:

for c in $(array[*]}
do
  echo -e " $c is in ......"
done

Wie kann ich das machen?

Antworten:


94

Aus der Antwort von anishsane und den darin enthaltenen Kommentaren wissen wir jetzt, was Sie wollen. Hier ist das Gleiche in einem bashier Stil mit einer for-Schleife. Siehe den Abschnitt Schleifenkonstrukte im Referenzhandbuch . Ich benutze auch printfanstelle von echo.

#!/bin/bash

array=( "Vietnam" "Germany" "Argentina" )
array2=( "Asia" "Europe" "America" )

for ((i=0;i<${#array[@]};++i)); do
    printf "%s is in %s\n" "${array[i]}" "${array2[i]}"
done

Eine andere Möglichkeit wäre die Verwendung eines assoziativen Arrays:

#!/bin/bash

declare -A continent

continent[Vietnam]=Asia
continent[Germany]=Europe
continent[Argentina]=America

for c in "${!continent[@]}"; do
    printf "%s is in %s\n" "$c" "${continent[$c]}"
done

Je nachdem, was Sie tun möchten, können Sie diese zweite Möglichkeit in Betracht ziehen. Beachten Sie jedoch, dass Sie die Reihenfolge, in der die Felder in der zweiten Möglichkeit angezeigt werden, nicht leicht steuern können (nun, es ist ein assoziatives Array, also keine wirkliche Überraschung).


Ich denke, es ist -anicht-A
Brian

2
@Brian -aist für indizierte Arrays (dh reguläre) und -Afür assoziative Arrays (Hash-Tabellen), also in diesem Fall -Akorrekt.
gniourf_gniourf

3
@ Brian vielleicht hast du eine alte Version von Bash. Assoziative Arrays wurden in Bash 4 angezeigt. Wenn dies der Fall ist, können Sie nur das erste Beispiel meines Beitrags verwenden, nicht das zweite.
gniourf_gniourf

Vielleicht ist es das. Das wusste ich nicht. Ich habe Ihr erstes Beispiel angeführt. Vielen Dank
Brian

Warum druckt die letzte Schleife Daten in umgekehrter Reihenfolge?
Borys

40

Wenn alle Arrays korrekt sortiert sind, übergeben Sie einfach den Index.

array=(
  Vietnam
  Germany
  Argentina
)
array2=(
  Asia
  Europe
  America
)

for index in ${!array[*]}; do 
  echo "${array[$index]} is in ${array2[$index]}"
done

Vietnam is in Asia
Germany is in Europe
Argentina is in America

18

Sie benötigen eine Schleife über Array & Array2

i=0
while [ $i -lt ${#array[*]} ]; do
    echo ${array[$i]} is in ${array2[$i]}
    i=$(( $i + 1));
done

Vietnam is in Asia
Germany is in Europe
Argentina is in America

BEARBEITEN: Verwenden Sie nicht die unten stehende trImplementierung. Es funktioniert nicht für Array-Elemente, die Leerzeichen enthalten. Nicht entfernen, um die Kommentare relevant zu halten. Siehe Glenn Jackmans Kommentar anstelle der folgenden Antwort.

/BEARBEITEN

Alternativ können Sie diese Option (ohne Schleife) verwenden:

paste <(tr ' ' '\n' <<< ${array[*]}) <(tr ' ' '\n' <<< ${array2[*]}) | sed 's/\t/ is in /'

3
Ich denke, das ist was du willst.
Anishsane

@ user2354862 Wenn dies der Fall ist, sollten Sie die Antwort akzeptieren .
Ansgar Wiechers

3
oder vermeiden Sie es, zweimal zu laichen:paste <(printf "%s\n" "${array[@]}") <(printf "%s\n" "${array2[@]}") | sed 's/\t/ is in /'
Glenn Jackman

3

Wenn die beiden Vars zwei Zeichenfolgen mit mehreren Zeilen wären, wie folgt:

listA=$(echo -e "Vietnam\nGermany\nArgentina")
listB=$(echo -e "Asia\nEurope\nAmerica")

Dann ist die Lösung für diesen Fall:

while read strA <&3 && read strB <&4; do
   echo "$strA is in $strB"
done 3<<<"$listA" 4<<<"$listB"

Sie befinden sich bereits in zwei Arrays und müssen nicht in Zeichenfolgen konvertiert werden.
runlevel0

2

Speziell für die gestellte Frage (Arrays mit 3 Elementen):

for i in $(seq 0 2) ; do echo "${array1[$i]} is in ${array2[$i]}" ; done


0
#!/bin/bash

read -p "Enter File name : " file

read -ra USERS <<< $(cut -d: -f1 ${file})
read -ra DIRS <<< $(cut -d: -f6 ${file})


if [ ${#USERS[@]} == ${#DIRS[@]} ]
then

echo "Same size arrays.."

THRO=$(expr ${#USERS[@]} - 1)

for i in `seq 0 ${THRO}`
do
useradd -G sftp_users -d /home/sftp${DIRS[$i]} -s /sbin/nologin ${USERS[$i]}
done


else

echo "need same size arrays.."

fi

Bei mir hat so etwas funktioniert. Ich habe versucht, mehrere Benutzer aus der Datei / etc / passwd eines anderen Servers zu erstellen. Keine generische Lösung, hat aber ihren Zweck erfüllt.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.