2011-01-09 19 views
33

Chcę wykonać następujące czynności, przeczytaj wiersz po wierszu pliku i użyć wartości jednej linii jako paramsCzytaj linia po linii w skrypcie bash

FILE="cat test" 
echo "$FILE" | \ 
while read CMD; do 
echo $CMD 
done 

ale kiedy zrobić echo $ CMD, to po prostu zwraca cat: S

Odpowiedz

55

To, co masz, to wstawienie tekstu w pętlę do tekstu "cat test".

Chcesz tylko:

cat test | \ 
while read CMD; do 
    echo $CMD 
done 
86
FILE=test 

while read CMD; do 
    echo "$CMD" 
done < "$FILE" 

Istnieją pewne dodatkowe ulepszenia, które mogą być wykonane (dzięki @RanyAlbegWein):

  • Dodaj IFS= tak że read nie będzie przycinać początkowe i końcowe spacje z każdej linii.
  • Dodaj -r do odczytu, aby zapobiec interpretacji ukośników odwrotnych jako sekwencji unikowych.
  • Małe litery CMD i FILE. Konwencja bash jest tylko środowiskową, a wewnętrzne zmienne powłoki wielkimi literami.
  • Użyj printf zamiast echo, co jest bezpieczniejsze, jeśli $cmd jest ciągiem takim jak -n, który echo interpretowałby jako flagę.

Wynik:

file=test 

while IFS= read -r cmd; do 
    printf '%s\n' "$cmd" 
done < "$file" 
+14

+1 za uniknięcie bezużytecznego użycia 'cat'. –

+5

+1 dla dostępności zmiennych poza pętlą – former

+5

+1 dla rury w pętli while. Chciałbym jednak zwrócić uwagę widzów oglądających, że można po prostu zadzwonić "podczas czytania; zrobić ', aby użyć wbudowanej zmiennej * ODPOWIEDŹ *. –

1

Czy chodziło Ci zrobić:

cat test | \ 
while read CMD; do 
echo $CMD 
done 
2

Jeśli chcesz użyć każdej linii pliku jako params wiersza polecenia do aplikacji możesz użyj polecenia xargs.

xargs -a <params_file> <command> 

A params plik z:

a 
b 
c 
d 

i tr.py Plik:

import sys 
print sys.argv 

Realizacja

xargs -a params ./tr.py 

daje wynik:

['./tr.py', 'a', 'b', 'c', 'd'] 
0

Poprawna wersja twojego skryptu jest następująca;

FILE="cat test" 
$FILE | \ 
while read CMD; do 
echo $CMD 
done 

Jednak ten rodzaj niezależności - wydanie polecenia w zmiennej o nazwie PLIK - jest niepotrzebne. Użyj jednego z rozwiązań już dostarczonych. Chciałem tylko wskazać twój błąd.

10

xargs to najbardziej elastyczne rozwiązanie do dzielenia danych wyjściowych na argumenty poleceń.

Jest również bardzo czytelny dla ludzi i łatwy w użyciu ze względu na prostą parametryzację.

Format to xargs -n $NUMLINES mycommand.

Na przykład, aby echo każda pojedyncza linia w pliku /tmp/tmp.txt chcesz zrobić:

cat /tmp/tmp.txt | xargs -n 1 echo 

lub w celu diff każda kolejna para plików wymienionych jako linie w pliku powyższej nazwy zrobiłbyś :

cat /tmp/tmp.txt | xargs -n 2 diff 

-n 2 instruuje xargs konsumować i przekazać odsunięte dwie linie, co już rurami do niego w danej chwili.

Można dostosować xargs, aby podzielić na ogranicznikach oprócz powrotu karetki/nowej linii.

Użyj man xargs i google, aby dowiedzieć się więcej o sile tego wszechstronnego narzędzia.

Powiązane problemy