BASH leser txt-fil og lagrer i matrisen

Jeg skriver mitt første BASH-skript, jeg har litt erfaring med c og c # så jeg tror logikken til programmet er riktig .. det er bare syntaksen er så komplisert fordi det tilsynelatende er milliarder måter å skrive det samme på!

Uansett er her manuset: det sjekker bare om argumentet (strengen) er i en bestemt fil. I så fall lagrer den hver linje i filen i en matrise og skriver et element i matrisen i en fil. Jeg er sikker på at det må være enklere måter å oppnå det på, men jeg vil øve litt med 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 

Denne koden returnerer bare det andre elementet av myArray (myArray[2] eller den andre linjen i filen) .. hvorfor?

Kommentarer

  • Hvilken relevans har \ t? Både teksten og resten av koden refererer bare til linjer.
  • Ikke et direkte svar, så det ' er bare et kommentar, men jeg ' d gjør dette med en a one liner grep; grep -P -o "(?<=$NOME\t).+"
  • @Patrick Classic XY-problem , så jeg synes kommentaren din skal være et svar. Den gjør tross alt det rette.

Svar

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

I Bash 4 kan IFS=$"\n" a=($(cat phonebook.txt)) erstattes med mapfile -t a < phonebook.txt.

grep -A1 skriver ut en linje etter kampen. -x deaktiverer regex som -F, men det samsvarer bare med komplett l ines.

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

Kommentarer

  • Du kanskje vil validere innholdet i filen først. Opp til deg.
  • -x deaktiverer ikke regex .
  • Forlater at $(cat phonebook.txt) unotert i den listekonteksten påkaller split + glob på utvidelsen. Her vil du ha delt del, men ikke glob -del, så den skal deaktiveres (set -o noglob).
  • Det skal være grep -xFe "$name" -A1 phonebook.txt eller grep -xFA1 -- "$name" phonebook.txt eller det vil ikke ' t fungerer riktig hvis $name starter med - eller $POSIXLY_CORRECT er i miljøet.
  • I bash er det ' enten [[ $string = $pattern ]] eller [[ $string = "$otherstring" ]]. Eller IOW, du må sitere ordutvidelser på høyre side av = operatøren i [[...]] hvis du ikke gjør ' vil ikke at det skal tas som et mønster.

Svar

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

Nyere versjoner av bash støtter assosiative matriser. Det ville gjøre det lettere:

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

Kommentarer

  • og hvordan vil du returnere varen til myArray [navn + 1]?
  • I det indekserte eksemplet hadde du allerede løsningen, så jeg kopierte ikke '.
  • Kan jeg være galt, men å bruke et slikt rør ville ikke gjøre myArray " usynlig " til utenfor løkken ???
  • @FredericYesidPe ñ aS á nchez Verken spørsmålet eller svaret mitt inneholder en pipeline, så jeg don ' t vet hva du snakker om.
  • " mens lest navn; " ser ut som en rørledning, uansett, jeg fant " erklær -a array " løser problemer jeg fikk før, takk !!! +1

Svar

I et spørsmål med tittelen « BASH leser txt-fil og lagres i array «Jeg føler at readarray fortjener en omtale. Et eksempel på denne metoden jeg bruker for å lese testfiler i en matrise vil være:

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

Det foregående laster inn en fil med IP-adresser – atskilt med nye linjer – inn i en matrise kalt « arrayIPblacklist «. Ville fungere på telefonbokfilen din. readarray ble introdusert i bash 4, så denne metoden vil ikke fungere på eldre verter som kjører tidligere bash-versjoner.

-t alternativet fjerner de nye linjeavgrensningene fra hvert element, for det meste du ikke vil at de skal inkluderes.

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

Kommentarer

  • Merk at det aksepterte svaret allerede nevnt mapfile som er et annet (om enn mer forvirrende) navn for readarray innebygd.
  • Min dårlig- ikke ' t se det. Takk @St é phaneChazelas!

Legg igjen en kommentar

Din e-postadresse vil ikke bli publisert. Obligatoriske felt er merket med *