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?

user2354862
quelle

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).

gniourf_gniourf
quelle
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
cthomaspdx
quelle
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 /'
anishsane
quelle
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"
Fabrício Pereira
quelle
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

runlevel0
quelle
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.

totes Schwimmbad
quelle