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
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
lubgrep -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!
grep -P -o "(?<=$NOME\t).+"