zmiana IFS tymczasowo przed pętlą for [duplikat]
Wiem, że SHELL
pozwala przypisać zmienne bezpośrednio przed poleceniem, tak że IFS=":" read a b c d <<< "$here_string"
działa ...
Zastanawiałem się, czy takie przypisania nie działają, gdy są wykonywane z instrukcjami złożonymi, takimi jak pętle? Próbowałem czegoś podobnego, IFS=":" for i in $PATH; do echo $i; done
ale skutkuje to błędem składni. Zawsze mogłem zrobić coś takiego oldIFS="$IFS"; IFS=":"; for....; IFS="$oldIFS"
, ale chciałem wiedzieć, czy jest jakiś sposób, w jaki mógłbym sprawić, by takie przypisania w wierszu działały dla instrukcji złożonych, takich jak for
pętle?
Odpowiedzi
for
jest słowem zastrzeżonym i jako taki podlega specjalnym zasadom :
Następujące słowa uznaje się za słowa zastrzeżone:
! {} case do done elif else esac fi for if in then do czasu
Takie uznanie ma miejsce tylko wtedy, gdy żaden ze znaków nie jest cytowany i gdy słowo to jest używane jako:
Pierwsze słowo polecenia
Pierwsze słowo występujące po jednym z zarezerwowanych słów innych niż case , for lub in
Trzecie słowo w poleceniu case (tylko w to ważne w tym przypadku)
Trzecie słowo w poleceniu for (tylko in i do są ważne w tym przypadku)
Jeśli spróbujesz
IFS=":" for i in $PATH; do echo $i; done
zgodnie z powyższymi regułami nie jest to for
pętla, ponieważ słowo kluczowe nie jest pierwszym słowem polecenia. Ale twój zamiar można osiągnąć dzięki
IFS=: printf '%s\n' $PATH
$PATH
podlega podziałowi na słowa :
zgodnie z oczekiwaniami, a każde wynikowe słowo jest wypisywane przez printf
, po którym następuje nowa linia.
Być może znasz to prawidłowe podejście:
while IFS= read -r line; do
while
jest pierwszym słowem polecenia, a IFS
przypisanie dotyczy read
, więc wszystko jest OK.