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
odergrep -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.
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 diereadarray
builtin. - Mein schlechtes ' sehe das nicht. Vielen Dank an @St é phaneChazelas!