Ограничивая наше внимание исключительно bash
, вэтот ответна Stack Overflow сообщается следующее.
extglob
флаг используетсяпарсером. Функции, составные команды и т. д. анализируются полностью перед выполнением. Таким образом,extglob
необходимо задать до того, как будет проанализировано содержимое; установка его во время выполнения, но после времени анализа не оказывает никакого влияния на ранее проанализированное содержимое.Вот почему нельзя запустить команду
shopt -s extglob; ls !(*.txt)
в одну строку (еслиextglob
ранее не задано), а необходимо добавить новую строку между двумя командами.
Однако это не относится к другим вариантам оболочки. Рассмотрим, например, следующее.
$ ls -a
. .. .hiddenFile file1 file2 file3
$ shopt dotglob
dotglob off
$ echo *
file1 file2 file3
$ shopt -s dotglob; echo *
.hiddenFile file1 file2 file3
Задокументировано ли где-нибудь, какие параметры оболочки используются анализатором extglob
и, следовательно, не могут быть включены в групповой команде, которая их использует?
вshopt
страница в bash
руководствеНичего о поведении, описанном выше, похоже, не упоминается.
решение1
Задокументировано ли где-нибудь, какие параметры оболочки используются анализатором, например extglob, и поэтому не могут быть включены в групповой команде, которая их использует?
Трудно доказать обратное, но я сомневаюсь, что существует исчерпывающий список.
Ниже приведены те, которые, по моему мнению, влияют на синтаксический анализ, могут быть и другие:
extglob
-- изменяет значение скобок, которые в противном случае являются специальным символомexpand_aliases
-- псевдонимы расширяются довольно рано в процессе обработкиextquote
-- изменяет значение некоторых цитатinteractive_comments
-- изменяет значение#
в начале слова.
Некоторые из compat*
вариантов также могут иметь схожие эффекты, но я оставлю их тестирование кому-то более заинтересованному.
С другой стороны, что-то вроде dotglob
, failglob
и globstar
влияет только на результат операции, а не на то, как она анализируется.
Что касается extglob
, командная строка типа !(foo)
действительна как с extglob
set, так и без него. С ним это глоб, который соответствует всем файлам, кроме foo
, а без него это подоболочка, запускающая команду foo
, с инвертированным возвращаемым значением.
Обратите внимание, что на практике это не должно быть проблемой. В скрипте вы можете поместить команду shopt
на отдельную строку, так что изменение в разборе повлияет на следующую строку без проблем. В однострочном скрипте вы можете использовать опцию -O
в командной строке, например, в bash -O extglob -c 'echo !(foo)'
, расширенный глоб работает.