|
|
ru.unix.bsd- RU.UNIX.BSD ------------------------------------------------------------------ From : Valentin Nechayev 2:5020/400 03 Feb 2003 16:53:46 To : "Maxim A. Samoilenko" Subject : Re: Bug or feature? -------------------------------------------------------------------------------- >>> Maxim A. Samoilenko wrote: MAS> Hикак не могу постичь одну вещь. MAS> smax@zeus[pf:0]~>echo $BASH_VERSION MAS> 2.05b.0(1)-release MAS> smax@zeus[pf:0]~>IFS=': '; echo 'blah : nah'| { \ >> { read a b c ; echo "a='$a' b='$b' c='$c'"; } MAS> a='blah' b='' c='nah' MAS> ^^^^ MAS> Откуда там пустое значение? MAS> Кого из нас глючит? Я таки вкурил POSIX и попытался разобраться, что тут происходит. Суть правил в Posix.1-2001/SUSv3 и SUSv2, как минимум, одинакова, цитирую: === cut === The shell shall treat each character of the IFS as a delimiter and use the delimiters to split the results of parameter expansion and command substitution into fields. 1. If the value of IFS is a <space>, <tab>, and <newline>, or if it is unset, any sequence of <space>s, <tab>s, or <newline>s at the beginning or end of the input shall be ignored and any sequence of those characters within the input shall delimit a field. For example, the input: <newline><space><tab>foo<tab><tab>bar<space> yields two fields, foo and bar. 2. If the value of IFS is null, no field splitting shall be performed. 3. Otherwise, the following rules shall be applied in sequence. The term " IFS white space" is used to mean any sequence (zero or more instances) of white space characters that are in the IFS value (for example, if IFS contains <space>/ <comma>/ <tab>, any sequence of <space>s and <tab>s is considered IFS white space). a. IFS white space shall be ignored at the beginning and end of the input. b. Each occurrence in the input of an IFS character that is not IFS white space, along with any adjacent IFS white space, shall delimit a field, as described previously. c. Non-zero-length IFS white space shall delimit a field. === end cut === Рассмотрим первый пример. IFS=': ' echo 'blah : nah ' | { read a b c; echo "a='$a' b='$b' c='$c'"; } Порядок символов в IFS не должен иметь значения (в другом месте есть правило, что в $* части соединяются первым символом из IFS, но это не для здесь). В IFS, определены пробел (в категории IFS white space) и ':' (в прочих). По пункту 3b, вся конструкция ' : ' должна считаться одним разделителем. В конце, должен пропуститься финальный IFS white space, по пункту 3a. Итого должно получиться: a='blah', b='nah', c=''. Смотрим: $ sh smax1 a='blah' b='' c=' nah ' $ bash smax1 a='blah' b='' c='nah' $ zsh smax1 a='blah' b='nah' c='' $ ksh smax1 a='blah' b='' c='nah' Такое поведение только у zsh. Теперь меняем местами символы в IFS (напоминаю, что тут их порядок не имеет значения). $ cat smax1.1 IFS=' :' echo 'blah : nah ' | { read a b c; echo "a='$a' b='$b' c='$c'"; } $ sh smax1.1 a='blah' b='nah' c='' $ bash smax1.1 a='blah' b='' c='nah' $ zsh smax1.1 a='blah' b='nah' c='' $ ksh smax1.1 a='blah' b='' c='nah' Hа этот раз sh и zsh показали правильно. По двум тестам, правильное поведение только у zsh. Остальные несут чушь. Теперь меняем ':' на Tab. $ cat smax2 IFS=`printf '\t '` printf 'blah \t nah\n' | { read a b c ; echo "a='$a' b='$b' c='$c'"; } $ sh smax2 a='blah' b='' c=' nah' $ bash smax2 a='blah' b='nah' c='' $ zsh smax2 a='blah' b='nah' c='' $ ksh smax2 a='blah' b='nah' c='' Тут работают правильно все кроме sh. Hесколько IFS white space должны разделять поля и не вставлять пустые поля внутри свой последовательности по правилу 3c. И только в последнем варианте все работают одинаково и правильно: $ cat smax2 IFS=`printf ' \t'` printf 'blah \t nah\n' | { read a b c ; echo "a='$a' b='$b' c='$c'"; } $ sh smax2 a='blah' b='nah' c='' $ bash smax2 a='blah' b='nah' c='' $ zsh smax2 a='blah' b='nah' c='' $ ksh smax2 a='blah' b='nah' c='' Вывод - пользуйтесь zsh ;))) P.S. Всё происходящее проверено на дефолтной локали. Если где-то пробел или Tab - не white space, я не виноват. -netch- --- ifmail v.2.15dev5 * Origin: Dark side of coredump (2:5020/400) Вернуться к списку тем, сортированных по: возрастание даты уменьшение даты тема автор
Архивное /ru.unix.bsd/7368657611a5.html, оценка из 5, голосов 10
|