Bash array überprüfen?

2 Antworten

j=0
while [[ $j -le ${#Arr2[@]} ]]; do 
  [[ "${Arr1[0]}" == "${Arr2[$j]}" ]] && echo "found"
  let j=j+1 
done

Das ist natürlich eher Pseudo-Code und natürlich würde man die Schleife sofort verlassen, wenn etwas gefunden wurde.

ArS123570 
Fragesteller
 25.01.2023, 16:05

Gibt es auch eine Möglichkeit "if" zu verwenden?

0
evtldocha  25.01.2023, 16:10
@ArS123570

Ja klar - ich habe ja nur einen Einzeiler gemacht.

j=0
while [[ $j -le ${#Arr2[@]} ]]; do 
  if [[ "${Arr1[0]}" == "${Arr2[$j]}" ]]; then
   echo "found"
   break
  fi
  let j=j+1
done

Das habe ich jetzt aber nicht weiter getestet.

1
wenn man viele Wörter in Arr2 gespeichert hat

Wie viel sind denn „viele“? Deine Version sieht zwar gruselig aus, ist aber deutlich schneller als alles, was mir an Alternativen einfällt. Bei 4 000 000 Werten messe ich:

Testumgebung: GNU bash, version 5.1.16(1)-release (x86_64-pc-linux-gnu)

Arr1 = 1001 # nicht in Arr2 enthalten
Arr2=( $(seq -1000001 3 11000000) ) # 4000001 Werte

Bemerkung: ${Arr2[*]/!($Arr1)} löscht jeden Eintrag != $Arr1. Übrig bleiben 4 Mio. leere Strings und ggf. der letzte Buchstabe eines exakten Treffers.

Mit time (built-in) gemessen:

  • 10,3s: for w in ${Arr2[*]}; do if test $w = $Arr1; then echo Yes; break; fi done
  • 2,9s: if test $(echo ${Arr2[*]/!($Arr1)})X != X; then echo Yes; fi
  • 2,6s: for w in ${Arr2[*]/!($Arr1)}; do echo Yes; break; done
  • 0,8s: if [[ " ${Arr2[*]} " =~ " $Arr1 " ]]; then echo Yes; fi

Alle Zeiten verhalten sich grob linear zur Länge von Arr2. Die Varianten mit for-Schleife werden marginal schneller, wenn der Eintrag früh gefunden wird.

Fazit: Deine Variante erschlägt 10 Millionen Einträge in ca. zwei Sekunden. Für ein Shellskript ist das gar nicht so nicht übel. Wenn Du mehr brauchst, musst Du wohl ein Python-Skript schreiben.

ralphdieter  25.01.2023, 23:42

Die Bash kann auch assoziative Arrays. Das Anlegen dauert etwas länger, aber der Zugriff geht dann wirklich flott (nicht messbar):

declare -A Arr2
for key in $(seq -f "K%.f" -1000000 3 29000000); do Arr2+=($key $key); done
if test -n "${Arr2[$Arr1]}"; then echo YES; else echo No; fi
2