временное изменение IFS перед циклом for [дубликат]
Я знаю, что SHELLпозволяет присваивать переменные непосредственно перед командой, так что IFS=":" read a b c d <<< "$here_string"работает ...
Мне было интересно, не работают ли такие назначения, когда они выполняются с помощью составных операторов, таких как циклы? Я пробовал что-то вроде, IFS=":" for i in $PATH; do echo $i; doneно это привело к синтаксической ошибке. Я всегда мог сделать что-то подобное oldIFS="$IFS"; IFS=":"; for....; IFS="$oldIFS", но я хотел знать, есть ли способ заставить такие встроенные назначения работать для составных операторов, таких как forциклы?
Ответы
forявляется зарезервированным словом и поэтому следует особым правилам :
Следующие слова признаются зарезервированными:
! {} case do done elif else esac fi for if in then до while
Это распознавание должно происходить только тогда, когда ни один из символов не цитируется и когда слово используется как:
Первое слово команды
Первое слово, следующее за одним из зарезервированных слов, кроме case , for или in
Третье слово в команде случае (только в действительно в данном случае)
Третье слово в команде for ( в этом случае допустимы только in и do )
Если вы пытаетесь
IFS=":" for i in $PATH; do echo $i; done
по приведенным выше правилам это не forцикл, так как ключевое слово не является первым словом команды. Но ваше намерение может быть достигнуто с помощью
IFS=: printf '%s\n' $PATH
$PATHподвергается разделению слов, :как ожидалось, и каждое полученное слово печатается с printfпоследующим переводом строки.
Возможно, вы знакомы с этим подходом:
while IFS= read -r line; do
whileэто первое слово команды, и IFSприсвоение применяется к read, так что все в порядке.