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
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
saugrep -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) pentrureadarray
builtin. - Rău mea ' nu am văzut asta. Mulțumim @St é phaneChazelas!
grep -P -o "(?<=$NOME\t).+"