Это сделано намеренно, чтобы избежать нарушения совместимости с POSIX (хотя изначально это было сделано, чтобы избежать нарушения совместимости с Bourne).
echo file_{2}([0-9])
будет недопустимым кодом в Bourne/POSIX sh
, поэтому ksh
может интерпретировать его как угодно. Но:
pattern='file_{2}([0-9])'
echo $pattern
является действительным кодом Bourne/POSIX sh
, и, согласно POSIX, предназначен для поиска файлов с именами типа file_{2}(0)
, file_{2}(1)
...
Расширенные операторы недоступны, когда они являются результатом расширения, даже если вы используете:
echo @($pattern)
Вам нужно использовать eval
, или вы можете использовать FIGNORE
:
FIGNORE="!($pattern)"; echo *
(обратите внимание, что это влияет на расширение скрытых файлов, сделайте FIGNORE="@(.*|!($pattern))"
, если вы не ожидаете, что glob расширит скрытые файлы).
Обратите внимание, что bash
и zsh
позже приняли некоторые из этих ksh
расширенных операторов (хотя и не {x,y}(.... )
), но совместимость с POSIX/Bourne они решили иначе: они сделали эти расширенные глобы доступными во всех контекстах, но только когда включена определенная опция (kshglob
в zsh
, extglob
в bash
). Однако это означает, что им трудно добавить больше операторов, не нарушая собственной обратной совместимости. Например, если bash
добавит оператор {x,y}(...)
, это может сломать скрипты, которые ожидают, что a='{1}(2){3}'; [[ $a = $a ]]
вернет true.