Ik schrijf mijn eerste BASH-script, ik heb enige ervaring met c en c #, dus ik denk dat de logica van de programma is correct .. het is alleen de syntaxis zo ingewikkeld omdat er blijkbaar miljarden manieren zijn om hetzelfde te schrijven!
Hoe dan ook, hier is het script: het controleert eenvoudig of het argument (string) is in een bepaald bestand. Als dit het geval is, slaat het elke regel van het bestand op in een array en schrijft het een item van de array in een bestand. Ik weet zeker dat er eenvoudiger manieren moeten zijn om dat te bereiken, maar ik wil wat oefenen met bash-loops
#!/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
Deze code retourneert het enige het tweede item van myArray (myArray[2]
of de tweede regel van het bestand) .. waarom?
Reacties
Antwoord
IFS=$"\n" a=($(cat phonebook.txt)) for i in $(seq ${#a[*]}); do [[ ${a[$i-1]} = $name ]] && echo "${a[$i]}" done
In Bash 4 kan IFS=$"\n" a=($(cat phonebook.txt))
worden vervangen door mapfile -t a < phonebook.txt
.
grep -A1 drukt één regel af na de overeenkomst. -x schakelt regex zoals -F uit maar komt alleen overeen met complete l ines.
grep -x "$name" -A1 phonebook.txt | tail -n1
Reacties
- U misschien wilt de inhoud van het bestand eerst. Aan jou.
-
-x
schakelt regex niet uit . - Dat laat
$(cat phonebook.txt)
niet aangehaald in die lijstcontext roept split + glob op bij de uitbreiding. Hier wil je het split -gedeelte, maar niet het glob -gedeelte, dus het moet worden uitgeschakeld (set -o noglob
). - Het moet
grep -xFe "$name" -A1 phonebook.txt
ofgrep -xFA1 -- "$name" phonebook.txt
zijn of het zal ' niet werken correct als$name
begint met-
of$POSIXLY_CORRECT
zich in de omgeving bevindt. - In
bash
is het '[[ $string = $pattern ]]
of[[ $string = "$otherstring" ]]
. Of IOW, je moet woorduitbreidingen aan de rechterkant van de=
operator binnen[[...]]
citeren als je niet ' wil dat het als een patroon wordt gebruikt.
Antwoord
index=0 while read line; do myArray[index]="$line" done < inputfile
Nieuwere versies van bash ondersteunen associatieve arrays. Dat zou het gemakkelijker maken:
declare -A myArray while read name; do read number myArray[name]="$number" done < inputfile echo ${myArray[name]}
Reacties
- en hoe zou je het item van myArray retourneren [naam + 1]?
- In het geïndexeerde voorbeeld had je de oplossing al, dus ik heb ' niet gekopieerd.
- Mag ik verkeerd zijn, maar het gebruik van een dergelijke pipe zou myArray " onzichtbaar " buiten de lus maken ???
- @FredericYesidPe ñ aS á nchez Noch de vraag, noch mijn antwoord bevat een pijplijn, dus ik don ' weet niet waar je het over hebt.
- " tijdens het lezen van naam; " ziet er voor mij uit als een pipeline, hoe dan ook, ik vond de " declare -a array " lost problemen op die ik eerder had, bedankt !!! +1
Antwoord
In een vraag met de titel “ BASH leest txt-bestand en slaat op in array “Ik vind dat readarray
een vermelding verdient. Een voorbeeld van deze methode die ik gebruik om testbestanden in een array te lezen, is:
readarray -t arrayIPblacklist < /etc/postfix/IP-black-list.txt
Het voorgaande laadt een bestand met IP-adressen – gescheiden door nieuwe regels – in een array genaamd “ arrayIPblacklist “. Zou werken aan uw telefoonboekbestand. readarray
werd geïntroduceerd in bash 4, dus deze methode “werkt niet op oudere hosts met eerdere bash-versies.
De -t
optie verwijdert de scheidingstekens voor nieuwe regels van elk element, omdat u ze meestal niet wilt opnemen.
$ 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>
Opmerkingen
- Merk op dat het geaccepteerde antwoord al
mapfile
vermeldde, wat een andere (zij het meer verwarrende) naam is voor dereadarray
ingebouwd. - Mijn slechte ' zie dat niet. Bedankt @St é phaneChazelas!
grep -P -o "(?<=$NOME\t).+"