BASH leest txt-bestand en slaat het op in array

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

  • Welke relevantie heeft de \ t? Zowel de tekst als de rest van de code verwijzen alleen naar regels.
  • Geen direct antwoord, dus ' is slechts een opmerking, maar ik ' heb dit gedaan met een one-liner grep; grep -P -o "(?<=$NOME\t).+"
  • @Patrick Classic XY-probleem , dus ik denk dat je opmerking een antwoord moet zijn. Het doet tenslotte het juiste.

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 of grep -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 de readarray ingebouwd.
  • Mijn slechte ' zie dat niet. Bedankt @St é phaneChazelas!

Geef een reactie

Het e-mailadres wordt niet gepubliceerd. Vereiste velden zijn gemarkeerd met *