BASH citind fișierul txt și stocând în matrice

Scriu primul meu script BASH, am o oarecare experiență cu c și c #, așa că cred că logica programul este corect .. doar sintaxa este atât de complicată, deoarece se pare că există miliarde de moduri de a scrie același lucru!

Oricum, aici este scriptul: verifică pur și simplu dacă argumentul (șirul) este cuprins într-un anumit fișier. Dacă da, stochează fiecare linie a fișierului într-o matrice și scrie un element al matricei într-un fișier. Sunt sigur că trebuie să existe modalități mai ușoare de a realiza acest lucru, dar vreau să fac niște practici cu bucle bash

 #!/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 

Acest cod returnează singurul al doilea element din myArray (myArray[2] sau a doua linie a fișierului) .. de ce?

Comentarii

  • Ce relevanță are \ t? Atât textul, cât și restul codului se referă doar la linii.
  • Nu este un răspuns direct, deci ' este doar un comentariu, dar eu ' aș face acest lucru cu grep one one one; grep -P -o "(?<=$NOME\t).+"
  • @Patrick Classic Problema XY , așa că cred că comentariul dvs. ar trebui să fie un răspuns. La urma urmei, face ceea ce trebuie.

Răspuns

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

În Bash 4 IFS=$"\n" a=($(cat phonebook.txt)) poate fi înlocuit cu mapfile -t a < phonebook.txt.

grep -A1 tipărește o linie după meci. -x dezactivează regex ca -F, dar se potrivește doar cu l complet ines.

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

Comentarii

  • Poți doriți să validați conținutul fișierului mai întâi. Depinde de tine.
  • -x nu dezactivează regex .
  • Lăsând acel $(cat phonebook.txt) necotat în contextul listei respective invocă split + glob pe expansiune. Aici, doriți partea split , dar nu partea glob , deci ar trebui dezactivată (set -o noglob).
  • Ar trebui să fie grep -xFe "$name" -A1 phonebook.txt sau grep -xFA1 -- "$name" phonebook.txt sau să câștige ' corect dacă $name începe cu - sau $POSIXLY_CORRECT se află în mediu.
  • În bash, ' este fie [[ $string = $pattern ]], fie [[ $string = "$otherstring" ]]. Sau IOW, trebuie să citați extinderi de cuvinte în partea dreaptă a operatorului = din interiorul [[...]] dacă nu faceți ' nu vreau ca acesta să fie luat ca model.

Răspuns

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

Versiunile mai noi ale bash acceptă matrici asociative. Acest lucru ar face mai ușor:

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

Comentarii

  • și cum ați returna elementul myArray [nume + 1]?
  • În exemplul indexat aveți deja soluția, așa că nu l-am copiat '.
  • Mai pot greșește, dar utilizarea unei astfel de conducte nu ar face myArray " invizibil " în afara buclei ???
  • @FredericYesidPe ñ aS á nchez Nici întrebarea, nici răspunsul meu nu conțin o conductă, așa că nu ' nu știu despre ce vorbiți.
  • " în timp ce citiți numele; " mi se pare ca un conductă, oricum, am găsit " declare -a matrice " remediază problemele pe care le-am primit înainte, mulțumesc !!! +1

Răspuns

Într-o întrebare intitulată „ BASH citind fișierul txt și stocând în matrice „Simt că readarray merită o mențiune. Un exemplu al acestei metode pe care îl folosesc pentru a citi fișierele de testare într-o matrice ar fi:

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

Cele de mai sus încarcă un fișier de adrese IP – separate prin linii noi – în o matrice numită „ arrayIPblacklist ”. Ar funcționa la fișierul agendei. readarray a fost introdus în bash 4, astfel încât această metodă nu a funcționat pe gazde mai vechi care rulează versiuni bash anterioare.

-t opțiunea elimină delimitatorii newline din fiecare element, deoarece de cele mai multe ori nu doriți ca acestea să fie incluse.

$ 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> 

Comentarii

  • Rețineți că răspunsul acceptat a menționat deja mapfile care este un alt nume (deși mai confuz) pentru readarray builtin.
  • Rău mea ' nu am văzut asta. Mulțumim @St é phaneChazelas!

Lasă un răspuns

Adresa ta de email nu va fi publicată. Câmpurile obligatorii sunt marcate cu *