BASH läser txt-fil och lagrar i array

Jag skriver mitt första BASH-skript, jag har lite erfarenhet av c och c # så jag tror logiken i programmet är korrekt .. det är bara syntaxen är så komplicerat eftersom det tydligen finns miljarder sätt att skriva samma sak!

Hur som helst är här manuset: det kontrollerar helt enkelt om argumentet (strängen) är i en viss fil. I så fall lagras varje rad i filen i en matris och skriver ett objekt i matrisen i en fil. Jag är säker på att det måste finnas enklare sätt att uppnå det men jag vill göra lite övning med bash loopar

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

Den här koden returnerar bara det andra objektet av myArray (myArray[2] eller filens andra rad) .. varför?

Kommentarer

  • Vilken relevans har \ t? Både texten och resten av koden hänvisar bara till rader.
  • Inte ett direkt svar, så det ' är bara ett kommentera, men jag ' d gör detta med en a-liner grep; grep -P -o "(?<=$NOME\t).+"
  • @Patrick Classic XY-problem , så jag tycker att din kommentar borde vara ett svar. Det gör trots allt rätt.

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)) ersättas med mapfile -t a < phonebook.txt.

grep -A1 skriver ut en rad efter matchningen. -x inaktiverar regex som -F men det matchar bara komplett l ines.

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

Kommentarer

  • Du kanske vill validera innehållet i filen först. Upp till dig.
  • -x inaktiverar inte regex .
  • Lämnar att $(cat phonebook.txt) som inte citerats i listkontexten åberopar split + glob på expansionen. Här vill du ha delad del, men inte glob -del, så den ska vara inaktiverad (set -o noglob).
  • Det borde vara grep -xFe "$name" -A1 phonebook.txt eller grep -xFA1 -- "$name" phonebook.txt eller så vann det ' ordentligt om $name börjar med - eller $POSIXLY_CORRECT finns i miljön.
  • I bash är det ' antingen [[ $string = $pattern ]] eller [[ $string = "$otherstring" ]]. Eller IOW, du måste citera ordutvidgningar till höger om = -operatören inuti [[...]] om du inte ' vill inte att det ska tas som ett mönster.

Svar

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

Nyare versioner av bash stöder associerande matriser. Det skulle göra det lättare:

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

Kommentarer

  • och hur skulle du returnera artikeln i myArray [namn + 1]?
  • I det indexerade exemplet hade du redan lösningen, så jag kopierade inte '.
  • Får jag vara fel, men att använda ett sådant rör skulle inte göra myArray " osynlig " utanför utsidan ???
  • @FredericYesidPe ñ aS á nchez Varken frågan eller mitt svar innehåller en pipeline så jag don ' t vet vad du pratar om.
  • " medan läst namn; " ser ut som en pipeline, hur som helst, jag hittade " deklarera -en array " fixar problem jag fick tidigare, tack !!! +1

Svar

I en fråga med titeln ” BASH läser txt-fil och lagras i array ”Jag tycker att readarray förtjänar att nämnas. Ett exempel på den här metoden jag använder för att läsa testfiler i en matris skulle vara:

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

Det föregående laddar en fil med IP-adresser – åtskilda av nya rader – i en matris som heter ” arrayIPblacklist ”. Skulle fungera på din telefonbokfil. readarray introducerades i bash 4, så den här metoden kommer inte att fungera på äldre värdar som kör tidigare bash-versioner.

-t alternativ tar bort de nya linjeavgränsarna från varje element, eftersom du oftast inte vill att de ska inkluderas.

$ 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

  • Observera att det accepterade svaret redan nämnt mapfile vilket är ett annat (om än mer förvirrande) namn för readarray inbyggd.
  • Min dåliga- såg inte ' det. Tack @St é phaneChazelas!

Lämna ett svar

Din e-postadress kommer inte publiceras. Obligatoriska fält är märkta *