2013-09-04 12 views
31

Mam proste polecenia bash, który wygląda jakPrzekierowanie wyjścia bash dla pętli

for i in `seq 2`; do echo $i; done; > out.dat 

Gdy uruchamia wyjście seq 2 jest wysyłany do terminala i nic nie jest wyjście do pliku danych (out.dat)

oczekuję norma się być przekierowany do out.dat jak to robi po prostu uruchamiając polecenie seq 2 > out.dat

Odpowiedz

60

Usuń średnik.

for i in `seq 2`; do echo "$i"; done > out.dat 

WSKAZÓWKI

również sugerowane przez Fredrik Pihl, staraj się nie używać plików binarnych zewnętrznych, kiedy nie są potrzebne, a przynajmniej kiedy praktycznie nie:

for i in {1..2}; do echo "$i"; done > out.dat 
for ((i = 1; i <= 2; ++i)); do echo "$i"; done > out.dat 
for i in 1 2; do echo "$i"; done > out.dat 

Należy także ostrożnie z wyjściami w words, które mogą powodować rozszerzenie nazwy ścieżki.

for A in $(echo '*'); do echo "$A"; done 

pokaże swoje pliki, a nie tylko dosłowne *.

$() jest również zalecana jako jaśniejsza składnia podstawień poleceń w powłokach Bash i POSIX niż w przypadku kliknięć (`) i obsługuje zagnieżdżanie.

Do czyszczenia roztwory dobrze mierzonej na zmienne

while read VAR; do 
    ... 
done < <(do something) 

I

read ... < <(do something) ## Could be done on a loop or with readarray. 

for A in "${ARRAY[@]}"; do 
    : 
done 

printf może być łatwiej alternatywę w stosunku do zamierzonej funkcji:

printf '%s\n' {1..2} > out.dat 
+1

Dlaczego 'seq' zamiast' for i in {1..2}; czy ... '? –

+0

@FredrikPihl Tak, lepiej. Lub '((i = 1; i <= 2; ++ i))' lub po prostu 'w 1 2' dla kompatybilności. Moja odpowiedź dotyczy tylko problemu z przekierowaniem, chociaż próbowałem go naprawić: '" $ i "'. – konsolebox

+0

Po prostu pomyślałem, że możesz zaktualizować swoją odpowiedź alternatywnym * lepszym * sposobem rozwiązania problemu bez uciekania się do używania zewnętrznych plików binarnych :-) –

5

Spróbuj:

(for i in `seq 2`; do echo $i; done;) > out.dat 
+0

To zadziałało. Czy istnieje zasób, na którym mogę przeczytać, co robi nawias/dlaczego jest wymagany. Czy możesz wyjaśnić? –

+3

Nie jest konieczne umieszczanie go na podpowłokach. Średnik musi zostać usunięty, aby przekierować część bloku. – konsolebox

+2

To prawda, wystarczy usunąć średnik w tym przypadku. Funkcja Subshell,(), może być używana do zbierania danych wyjściowych z większej liczby poleceń, np. Wielu pętli for. – svante

6

Inna możliwość, ze względu na kompletność: Możesz przesunąć wyjście insi w pętli, używając >> do dołączenia do pliku, jeśli istnieje.

for i in `seq 2`; do echo $i >> out.dat; done; 

Który z nich jest lepszy, na pewno zależy od przypadku użycia. Zapisanie pliku za jednym razem jest z pewnością lepsze niż dołączanie do niego tysiąc razy. Ponadto, jeśli pętla zawiera wiele instrukcji echo, z których wszystkie powinny przejść do pliku, wykonanie done > out.dat jest prawdopodobnie bardziej czytelne i łatwiejsze w utrzymaniu. Zaletą tego rozwiązania jest oczywiście większa elastyczność.

+3

Wykonanie pojedynczego przekierowania poza pętlą jest zdecydowanie lepsze dla wydajności. – tripleee

Powiązane problemy