BASH odczytuje plik txt i przechowuje w tablicy

Piszę swój pierwszy skrypt BASH, mam pewne doświadczenie z c i c #, więc myślę, że logika program jest poprawny … po prostu składnia jest tak skomplikowana, ponieważ najwyraźniej istnieją miliardy sposobów na napisanie tego samego!

W każdym razie tutaj jest skrypt: po prostu sprawdza, czy argument (łańcuch) jest zawarte w określonym pliku. Jeśli tak, to przechowuje każdy wiersz pliku w tablicy i zapisuje element tablicy w pliku. Jestem pewien, że muszą istnieć prostsze sposoby, aby to osiągnąć, ale chcę poćwiczyć z pętlami basha

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

Ten kod zwraca tylko drugą pozycję of myArray (myArray[2] lub druga linia pliku) .. dlaczego?

Komentarze

  • Jakie znaczenie ma \ t? Zarówno tekst, jak i reszta kodu odnoszą się tylko do wierszy.
  • Nie jest to bezpośrednia odpowiedź, więc ' to tylko komentarz, ale ja ' d zrobię to z one a one liner grep; grep -P -o "(?<=$NOME\t).+"
  • @Patrick Classic XY problem , więc myślę, że twój komentarz powinien być odpowiedzią. W końcu robi to dobrze.

Odpowiedź

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

W Bash 4 IFS=$"\n" a=($(cat phonebook.txt)) można zastąpić mapfile -t a < phonebook.txt.

grep -A1 wyświetla jedną linię po dopasowaniu. -x wyłącza wyrażenie regularne takie jak -F, ale pasuje tylko do pełnego l ines.

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

Komentarze

  • Możesz zweryfikować zawartość pliku. Do Ciebie.
  • -x nie wyłącza wyrażenia regularnego .
  • Pozostawienie $(cat phonebook.txt) bez cudzysłowu w tym kontekście listy wywołuje split + glob przy rozwinięciu. Tutaj potrzebujesz części split , ale nie części glob , więc powinna być wyłączona (set -o noglob).
  • Powinien być grep -xFe "$name" -A1 phonebook.txt lub grep -xFA1 -- "$name" phonebook.txt albo wygrał ' t poprawnie, jeśli $name zaczyna się od - lub $POSIXLY_CORRECT znajduje się w środowisku.
  • W bash ' jest [[ $string = $pattern ]] lub [[ $string = "$otherstring" ]]. Lub IOW, musisz zacytować rozwinięcia słów po prawej stronie operatora = wewnątrz [[...]], jeśli nie ' nie chcę, aby był traktowany jako wzorzec.

Odpowiedź

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

Nowsze wersje basha obsługują tablice asocjacyjne. To by było łatwiejsze:

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

Komentarze

  • i w jaki sposób można zwrócić element myArray [imię + 1]?
  • W zindeksowanym przykładzie masz już rozwiązanie, więc nie ' nie skopiowałem go.
  • Mogę będzie źle, ale użycie takiej potoku nie spowoduje, że myArray " będzie niewidoczne " poza pętlą ???
  • @FredericYesidPe ñ aS á nchez Ani pytanie, ani moja odpowiedź nie zawierają potoku, więc nie ' wiem, o czym mówisz.
  • " podczas czytania nazwy; " wygląda dla mnie jak potok, w każdym razie, znalazłem " deklarację -a array " rozwiązuje problemy, które napotkałem wcześniej, dzięki !!! +1

Odpowiedź

W pytaniu zatytułowanym „ BASH odczytuje plik txt i zapisuje w tablicy „Uważam, że readarray zasługuje na wzmiankę. Przykładem tej metody, której używam do wczytywania plików testowych do tablicy, jest:

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

Powyższe ładuje plik z adresami IP – oddzielonymi znakami nowej linii – do tablica o nazwie „ arrayIPblacklist ”. Będzie działać na pliku książki telefonicznej. readarray został wprowadzony w bash 4, więc ta metoda nie działa na starszych hostach z wcześniejszymi wersjami basha.

-t usuwa separatory nowej linii z każdego elementu, ponieważ w większości przypadków nie chcesz ich uwzględniać.

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

Komentarze

  • Zauważ, że zaakceptowana odpowiedź została już wspomniana mapfile, która jest inną (choć bardziej mylącą) nazwą readarray builtin.
  • Mój zły – nie ' tego nie widziałem. Dzięki @St é phaneChazelas!

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *