BASH liest eine txt-Datei und speichert sie im Array

Ich schreibe mein erstes BASH-Skript. Ich habe einige Erfahrungen mit c und c #, daher denke ich an die Logik des Das Programm ist korrekt. Es ist nur so, dass die Syntax so kompliziert ist, weil es anscheinend Milliarden von Möglichkeiten gibt, dasselbe zu schreiben!

Wie auch immer, hier ist das Skript: Es prüft einfach, ob das Argument (Zeichenfolge) ist in einer bestimmten Datei enthalten. In diesem Fall wird jede Zeile der Datei in einem Array gespeichert und ein Element des Arrays in eine Datei geschrieben. Ich bin mir sicher, dass es einfachere Wege geben muss, um dies zu erreichen, aber ich möchte etwas Übung mit Bash-Schleifen machen.

 #!/bin/bash NOME=$1 c=0 #IF NAME IS FOUND IN THE PHONEBOOK THANK STORE EACH LINE OF THE FILE INTO ARRAY #ONCE THE ARRAY IS DONE GET THE INDEX OF MATCHING NAME AND RETURN ARRAY[INDEX+1] if grep "$NOME" /root/phonebook.txt ; then echo "CREATING ARRAY" while read line do myArray[$c]=$line # store line c=$(expr $c + 1) # increase counter by 1 done < /root/phonebook.txt else echo "Name not found" fi c=0 for i in myArray; do if myArray[$i]="$NOME" ; then echo ${myArray[i+1]} >> /root/numbertocall.txt fi done 

Dieser Code gibt nur das zweite Element zurück von myArray (myArray[2] oder die zweite Zeile der Datei) .. warum?

Kommentare

  • Welche Relevanz hat das \ t? Sowohl der Text als auch der Rest des Codes beziehen sich nur auf Zeilen.
  • Keine direkte Antwort, daher ist ' nur eine Kommentar, aber ich ' würde dies mit einem One-Liner-Grep tun; grep -P -o "(?<=$NOME\t).+"
  • @Patrick Classic XY-Problem , daher denke ich, dass Ihr Kommentar eine Antwort sein sollte. Er macht schließlich das Richtige.

Antwort

IFS=$"\n" a=($(cat phonebook.txt)) for i in $(seq ${#a[*]}); do [[ ${a[$i-1]} = $name ]] && echo "${a[$i]}" done 

In Bash 4 kann IFS=$"\n" a=($(cat phonebook.txt)) durch mapfile -t a < phonebook.txt.

grep -A1 druckt eine Zeile nach der Übereinstimmung. -x deaktiviert Regex wie -F, stimmt jedoch nur mit vollständigem l überein ines.

grep -x "$name" -A1 phonebook.txt | tail -n1 

Kommentare

  • Möglicherweise möchten Sie die überprüfen Inhalt der Datei zuerst. Es liegt an Ihnen.
  • -x deaktiviert den regulären Ausdruck nicht.
  • Belassen Sie diesen $(cat phonebook.txt), das in diesem Listenkontext nicht zitiert ist, ruft bei der Erweiterung split + glob auf. Hier möchten Sie den split -Teil, aber nicht den glob -Teil, daher sollte er deaktiviert sein (set -o noglob).
  • Es sollte grep -xFe "$name" -A1 phonebook.txt oder grep -xFA1 -- "$name" phonebook.txt sein oder es wird ' nicht funktionieren Richtig, wenn $name mit - beginnt oder $POSIXLY_CORRECT in der Umgebung ist.
  • In bash ist ' entweder [[ $string = $pattern ]] oder [[ $string = "$otherstring" ]]. Oder IOW, Sie müssen Worterweiterungen auf der rechten Seite des Operators = in [[...]] angeben, wenn Sie nicht ' möchte nicht, dass es als Muster verwendet wird.

Antwort

index=0 while read line; do myArray[index]="$line" done < inputfile 

Neuere Versionen von Bash unterstützen assoziative Arrays. Das würde es einfacher machen:

declare -A myArray while read name; do read number myArray[name]="$number" done < inputfile echo ${myArray[name]} 

Kommentare

  • und wie würden Sie das Element von myArray zurückgeben [name + 1]?
  • In dem indizierten Beispiel hatten Sie bereits die Lösung, daher habe ich sie ' nicht kopiert.
  • Darf ich falsch sein, aber die Verwendung einer solchen Pipe würde myArray " nicht unsichtbar machen " außerhalb der Schleife ???
  • @FredericYesidPe ñ aS á nchez Weder die Frage noch meine Antwort enthalten eine Pipeline, daher

weiß nicht, wovon du sprichst.

  • " während der Name gelesen wird; " sieht für mich wie ein aus Pipeline jedenfalls fand ich die " deklarieren -a Array " behebt Probleme, die ich zuvor hatte, danke !!! +1
  • Antwort

    In einer Frage mit dem Titel „ BASH liest txt-Datei und speichert in Array „Ich denke, readarray verdient eine Erwähnung. Ein Beispiel für diese Methode, die ich zum Einlesen von Testdateien in ein Array verwende, wäre:

    readarray -t arrayIPblacklist < /etc/postfix/IP-black-list.txt 

    Das Vorstehende lädt eine Datei mit IP-Adressen, die durch Zeilenumbrüche getrennt sind ein Array namens „ arrayIPblacklist „. Würde auf Ihrer Telefonbuchdatei funktionieren. readarray wurde in Bash 4 eingeführt, sodass diese Methode auf älteren Hosts mit früheren Bash-Versionen nicht funktioniert.

    Die -t werden die Newline-Trennzeichen von jedem Element entfernt, da sie meistens nicht enthalten sein sollen.

    $ seq 3 | bash -c "readarray a; printf "<%q>\n" "${a[@]}"" <$"1\n"> <$"2\n"> <$"3\n"> $ seq 3 | bash -c "readarray -t a; printf "<%q>\n" "${a[@]}"" <1> <2> <3> 

    Kommentare

    • Beachten Sie, dass in der akzeptierten Antwort bereits mapfile erwähnt wurde. Dies ist ein anderer (wenn auch verwirrenderer) Name für die readarray builtin.
    • Mein schlechtes ' sehe das nicht. Vielen Dank an @St é phaneChazelas!

    Schreibe einen Kommentar

    Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.