2012-07-05 16 views
27

Powiel możliwe:
Looping through the content of a file in Bash?Jak mogę iterować liniami w zewnętrznym pliku z powłoką?

Mam jeden plik z listą nazwisk. Muszę przechwytywać wszystkie nazwy w tym pliku z zewnętrznego pliku ze skryptem powłoki. Jak mogę to zrobić?

Przykładowe pliki:

scripts/names.txt

alison 
barb 
charlie 
david 

scripts/script.sh

NAMES="" #names from names.txt file 
for NAME in $NAMES; do 
    echo "$NAME" 
done 

Jak mogę eksplodować plik names.txt do tablicy w oddzielnym Skrypt powłoki?

+1

Jak o link do oryginalnego Q & A? – bearvarine

Odpowiedz

54

Jednym ze sposobów byłoby:

while read NAME 
do 
    echo "$NAME" 
done < names.txt 

EDIT: Zauważ, że pętla zostanie wykonany w pod- powłoka, więc wszelkie zmodyfikowane zmienne będą lokalne, chyba że zadeklarujesz je z declare poza pętlą.

Dennis Williamson ma rację. Przepraszam, musiałem używać konstruktorów rurowych zbyt często i byłem zdezorientowany.

+2

Nie, ponieważ nic nie jest podłączone do 'while', nie ma podpowłok. Przekierowanie do 'done' nie tworzy podpowłoki. –

+0

Nawiasem mówiąc, problem (błąd?) Z potokami nie występuje z powłoką Korn (ale działa z pdksh). – cdarke

5

Wiem, że purystom nienawidzi ta metoda, ale możesz cat plik.

NAMES=`cat scripts/names.txt` #names from names.txt file 
for NAME in $NAMES; do 
    echo "$NAME" 
done 
+5

Ma to tę zaletę, że nie wywołuje podrzędnej powłoki, ale uwzględnia dowolne miejsce w pliku 'names.txt' jako ogranicznik. – smocking

+2

"Puryści" będą pomocni wyjaśnić, co jest z tym nie tak. Istnieje wiele problemów. Zobacz http://mywiki.wooledge.org/DontReadLinesWithFor – tripleee

6
cat names.txt|while read line; do 
    echo "$line"; 
done 
+4

'while read line; robić ...; done

13

Będziesz chciał użyć „czytać” Command

while read name 
do 
    echo "$name" 
done < names.txt 

uwaga, że ​​„$ name” jest cytowany - jeśli nie, zostanie on podzielony za pomocą znaków w $IFS jako ograniczniki. To prawdopodobnie nie zostanie zauważone, jeśli po prostu echo zmiennej, ale jeśli plik zawiera listę nazw plików, które chcesz skopiować, zostaną one podzielone przez $IFS, jeśli zmienna jest niecytowana, co nie jest tym, co chcą lub oczekują.

Jeśli chcesz użyć podejście Mike'a Clarka (ładowanie do zmiennej zamiast używać czytać), można to zrobić bez użycia cat:

NAMES="$(< scripts/names.txt)" #names from names.txt file 
for NAME in $NAMES; do 
    echo "$NAME" 
done 

Problem z tym jest to, że ładuje całość plik do $NAMES, po przeczytaniu go z powrotem, można albo uzyskać cały plik (jeśli zacytowano) lub plik z podziałem na $IFS, jeśli nie jest cytowany. Domyślnie daje to pojedyncze słowa, a nie poszczególne wiersze. Więc jeśli nazwa "Mary Jane" pojawiłaby się na linii, otrzymalibyśmy "Mary" i "Jane" jako dwie oddzielne nazwy. Korzystanie read będzie obejść ten problem ... chociaż można także zmienić wartość $IFS

2

To może pracować dla Ciebie:

cat <<\! >names.txt 
> alison 
> barb 
> charlie 
> david 
> ! 
OIFS=$IFS; IFS=$'\n'; NAMES=($(<names.txt)); IFS=$OIFS 
echo "${NAMES[@]}" 
alison barb charlie david 
echo "${NAMES[0]}" 
alison 
for NAME in "${NAMES[@]}";do echo $NAME;done 
alison 
barb 
charlie 
david 
Powiązane problemy