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
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
ellergrep -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örreadarray
inbyggd. - Min dåliga- såg inte ' det. Tack @St é phaneChazelas!
grep -P -o "(?<=$NOME\t).+"