Bash pozwala na użycie: cat <(echo "$FILECONTENT")
Bash pozwala również na użycie: while read i; do echo $i; done </etc/passwd
aby połączyć poprzednie dwa, można użyć: echo $FILECONTENT | while read i; do echo $i; done
Problem z ostatnią polega na tym, że tworzy ona podpowłokę i po zakończeniu pętli while i
nie ma już dostępu do zmiennej .
Moje pytanie brzmi:
Jak osiągnąć coś takiego: while read i; do echo $i; done <(echo "$FILECONTENT")
czyli innymi słowy: skąd mam pewność, że i
przetrwa pętlę while?
Zwróć uwagę, że jestem świadomy dołączenia instrukcji while do, {}
ale to nie rozwiązuje problemu (wyobraź sobie, że chcesz użyć pętli while w funkcji i i
zmiennej zwracanej )
bash
while-loop
stdin
pipe
Wakan Tanka
źródło
źródło
lastpipe
oraz ich wady i zalety.Odpowiedzi:
Prawidłowy zapis zastępowania procesu to:
while read i; do echo $i; done < <(echo "$FILECONTENT")
Ostatnia wartość
i
przypisana w pętli jest wtedy dostępna po zakończeniu pętli. Alternatywą jest:echo $FILECONTENT | { while read i; do echo $i; done ...do other things using $i here... }
Nawiasy klamrowe są operacją grupowania we / wy i same nie tworzą podpowłoki. W tym kontekście są one częścią potoku i dlatego są uruchamiane jako podpowłoka, ale dzieje się tak z powodu
|
, a nie{ ... }
. Wspomniałeś o tym w pytaniu. AFAIK, możesz wykonać zwrot z tych elementów wewnątrz funkcji.Bash zapewnia również
shopt
wbudowaną, a jedną z wielu opcji jest:Dlatego użycie czegoś takiego w skrypcie sprawia, że zmodyfikowany plik jest
sum
dostępny po pętli:FILECONTENT="12 Name 13 Number 14 Information" shopt -s lastpipe # Comment this out to see the alternative behaviour sum=0 echo "$FILECONTENT" | while read number name; do ((sum+=$number)); done echo $sum
Robienie tego w wierszu poleceń zwykle powoduje błąd „kontrola zadań nie jest aktywna” (to znaczy w wierszu poleceń kontrola zadań jest aktywna). Testowanie tego bez użycia skryptu nie powiodło się.
Ponadto, jak zauważył Gareth Rees w swojej odpowiedzi , czasami możesz użyć tutaj ciągu :
while read i; do echo $i; done <<< "$FILECONTENT"
To nie wymaga
shopt
; możesz być w stanie zapisać proces za jego pomocą.źródło
while read i; do echo $i; done < <(cat /etc/passwd); echo $i
nie wróciłem do ostatniej linii dwa razy. Co robię źle?i
do pustego, więc echo po pętli powtarza pusty wiersz.while read i; do x=$i; done < <(cat /etc/passwd); echo i=$i; echo x=$x
działał, // może wtedy zmieniło się zachowanie basha?Jonathan Leffler wyjaśnia, jak robić to, co chcesz, używając podstawiania procesów , ale inną możliwością jest użycie tutaj ciągu :
while read i; do echo "$i"; done <<<"$FILECONTENT"
To oszczędza proces.
źródło
Ta funkcja tworzy duplikaty $ NUM razy plików jpg (bash)
function makeDups() { NUM=$1 echo "Making $1 duplicates for $(ls -1 *.jpg|wc -l) files" ls -1 *.jpg|sort|while read f do COUNT=0 while [ "$COUNT" -le "$NUM" ] do cp $f ${f//sm/${COUNT}sm} ((COUNT++)) done done }
źródło