2009-09-21 21 views
8

Mogłem to zrobić w jakimkolwiek innym języku, ale z Bashem wyglądałem bardzo szeroko i nie mogłem znaleźć odpowiedzi.Ręczne wykonywanie iteracji linii pliku | bash

Muszę ręcznie zwiększyć $line w skrypcie. Przykład:

for line in `cat file` 
do 
foo() 
     foo_loop(condition) 
{ 
do_something_to_line($line) 
} 
done 

Jeśli zauważysz, za każdym razem foo_loop iteracje, $line pozostaje taka sama. Muszę tam powtórzyć numer $line i upewnić się, że oryginalna pętla zawiera tylko liczbę wierszy w pliku.

Zastanawiałem się nad znalezieniem liczby wierszy w pliku przy użyciu innej pętli i iterowaniem zmiennej liniowej wewnątrz wewnętrznej pętli foo().

Wszelkie pomysły?

EDIT:

Przepraszam za tak niejasne.

Zaczynamy:

Próbuję zrobić sekcję mojego kodu wykonać wielokrotnie (wykonanie równoległe)

Function foo() # Does something 
for line in `cat $temp_file`; 
foo($line) 

Ten kod działa dobrze, ponieważ foo właśnie biorąc w wartość linii; ale gdybym chciał to zrobić:

Function foo() # Does something 
for line in `cat $temp_file`; 
while (some condition) 
foo($line) 
end 

$line wyniesie taką samą wartość całej pętli while. Potrzebuję go zmienić za pomocą pętli while, a następnie kontynuować, gdy powróci do for. Przykład:

line = Hi 
foo{ echo "$line" }; 
for line in `cat file`; 
while (number_of_processes_running -lt max_number_allowed) 
foo($line) 
end 

Jeśli zawartość pliku zostały

Hi \n Bye \n Yellow \n Green \n 

Wyjście przykładowego programu to (jeśli maksymalna ilość pozostawiano 3)

Hi Hi Hi Bye Bye Bye Yellow Yellow Yellow Green Green Green. 

Tam, gdzie ma to być

Hi Bye Yellow Green 

Mam nadzieję to jest lepsze. Staram się wyjaśnić mój problem.

+0

Myślę, że potrzebujemy jaśniejszego przykładu tego, co próbujesz osiągnąć. foo() wydaje się definiować funkcję powłoki w pętli, której nie jestem pewien, czego chcesz. –

Odpowiedz

16

Zamiast używać pętli for do odczytywania pliku, powinieneś przeczytać ten plik w ten sposób.

#!bin/bash 

while read line 
do 
    do_something_to_line($line) 
done < "your.file" 
+0

Należy zauważyć, że nie będzie to działać poprawnie dla linii z odwróconymi ukośnikami (read usuwa je) i wiodącymi i/lub końcowymi białymi znakami (również usuniętymi). Odpowiednim sposobem jest użycie 'read -r line' w celu uniknięcia usunięcia odwrotnego ukośnika i ustawienia' IFS = 'w celu uniknięcia usuwania białych znaków. – Jens

6

Krótko mówiąc, while read line; do _____ ; done

Następnie upewnij się, że masz podwójne cudzysłowy wokół „$ LINE” tak, że parametr nie jest rozdzielany spacjami.

Przykład:

$ cat /proc/cpuinfo | md5sum 
c2eb5696e59948852f66a82993016e5a *- 

$ cat /proc/cpuinfo | while read line; do echo "$line"; done | md5sum 
c2eb5696e59948852f66a82993016e5a *- 

Drugi przykład # dodać.gz do każdego pliku w bieżącym katalogu: # Jeśli jakiekolwiek pliki miały spacje, polecenie mv dla tej linii zwróci błąd.

$ find -type f -maxdepth 1 | while read line; do mv "$line" "$line.gz"; done 
+1

-1 za bezużyteczne użycie kota. Czy wiesz, że możesz przekierowywać również do komend złożonych? 'podczas czytania ...; robić ...; done Jens

1

Powinieneś dodawać obserwacje jako edycje do swojego pytania lub w komentarzach, a nie jako odpowiedź.

tej struktury:

while read line 
do 
    for ((i=1; i<$max_number_allowed; i++)) 
    do 
     foo $line 
    done 
done < file 

Wydajność:

Hi 
Hi 
Hi 
Bye 
Bye 
Bye 
...etc.

Podczas tego:

for ((i=1; i<$max_number_allowed; i++)) 
do 
    while read line 
    do 
     foo $line 
    done < file 
done 

Wynik:

Hi 
Bye 
Yellow 
Green 
Hi 
Bye 
Yellow 
Green 
...etc.
Powiązane problemy