Jak poprawnie iterować po liniach w bash albo w zmiennej, albo w wyniku polecenia? Po prostu ustawienie zmiennej IFS na nową linię działa na wyjściu polecenia, ale nie podczas przetwarzania zmiennej zawierającej nowe linie.
Na przykład
#!/bin/bash
list="One\ntwo\nthree\nfour"
#Print the list with echo
echo -e "echo: \n$list"
#Set the field separator to new line
IFS=$'\n'
#Try to iterate over each line
echo "For loop:"
for item in $list
do
echo "Item: $item"
done
#Output the variable to a file
echo -e $list > list.txt
#Try to iterate over each line from the cat command
echo "For loop over command output:"
for item in `cat list.txt`
do
echo "Item: $item"
done
Daje to wynik:
echo:
One
two
three
four
For loop:
Item: One\ntwo\nthree\nfour
For loop over command output:
Item: One
Item: two
Item: three
Item: four
Jak widać, echo zmiennej lub iteracja nad cat
poleceniem wypisuje kolejno każdą z linii. Jednak pierwsza dla pętli drukuje wszystkie elementy w jednym wierszu. Jakieś pomysły?
Odpowiedzi:
W przypadku bash, jeśli chcesz osadzić znaki nowego wiersza, dołącz ciąg znaków
$''
:A jeśli masz już taki ciąg w zmiennej, możesz czytać go wiersz po wierszu za pomocą:
źródło
done <<< "$list"
jest to kluczowedone <<< "$list"
jest kluczowy, ponieważ przekazuje „$ list” jako dane wejściowe doread
$list
jest bardzo ważne.echo "$list" | while ...
może wydawać się wyraźniejszy niż... done <<< "$line"
Możesz użyć
while
+read
:Btw.
-e
opcjaecho
jest niestandardowa.printf
Zamiast tego użyj , jeśli chcesz mieć przenośność.źródło
<<<
wersja sugerowane przez Glenn Jackman ma pracować ze zmienną zadania.while
część.<<<
Wersja nie robi (w nowych wersjach bash, przynajmniej).źródło
IFS=$'\n'
tego samego efektu.Oto zabawny sposób wykonania pętli for:
Trochę bardziej sensownym / czytelnym byłoby:
Ale to wszystko jest zbyt skomplikowane, potrzebujesz tylko miejsca:
Twoja
$line
zmienna nie zawiera znaków nowej linii. Zawiera przypadki,\
po których następujen
. Możesz to wyraźnie zobaczyć dzięki:Podstawienie polega na zamianie spacji, co wystarcza, aby zadziałało w przypadku pętli:
Próbny:
źródło
cr
, możesz użyć$'\n'
.Możesz także najpierw przekonwertować zmienną na tablicę, a następnie wykonać iterację.
Przydaje się to tylko wtedy, gdy nie chcesz zadzierać,
IFS
a także masz problemy zread
poleceniem, co może się zdarzyć, jeśli wywołasz inny pętlę w pętli, że ten skrypt może opróżnić bufor odczytu przed powrotem, tak jak to się stało .źródło