Главная страница


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)
 
 

Вернуться к списку тем, сортированных по: возрастание даты  уменьшение даты  тема  автор 

 Тема:    Автор:    Дата:  
 Bug or feature?   Maxim A. Samoilenko   27 Jan 2003 14:26:30 
 Re: Bug or feature?   Valentin Nechayev   03 Feb 2003 16:53:46 
 Re: Bug or feature?   Valentin Nechayev   03 Feb 2003 16:53:47 
Архивное /ru.unix.bsd/7368657611a5.html, оценка 2 из 5, голосов 10
Яндекс.Метрика
Valid HTML 4.01 Transitional