Почему бы мне не оставить extglob включен в bash?

Я только что узнал о опции оболочки bash extglob здесь: - Как использовать обратные или отрицательные подстановочные знаки при сопоставлении шаблонов в оболочке unix/linux?

Все ответы, которые использовали shopt -s extglob, также упомянули shopt -u extglob, чтобы отключить его. Почему я хочу превратить что-то настолько полезное? Действительно, почему это не по умолчанию? Предположительно, он может дать некоторые неприятные сюрпризы. Что они?

Ответ 1

Никаких неприятных сюрпризов - поведение по умолчанию не существует для совместимости с традиционным синтаксисом шаблонов, совместимым с стандартами.


То есть: Возможно (хотя и маловероятно), что кто-то, пишущий fo+(o).*, на самом деле предполагал, что + и круглые скобки рассматриваются как буквальные части шаблона, соответствующие их коду. Для bash интерпретировать это выражение по-другому, чем то, что требует спецификация POSIX sh, было бы нарушить совместимость, которая сейчас выполняется по умолчанию в очень немногих случаях (echo -e с xpg_echo unset is only one что сразу приходит на ум).

Это отличается от обычного случая, когда расширения bash расширяют поведение undefined по стандарту POSIX - случаи, когда базовая оболочка POSIX обычно генерирует ошибку, но bash вместо этого предлагает новое и различное явно задокументированное поведение - поскольку необходимость рассматривать эти символы в качестве совпадения определяется POSIX.

Чтобы процитировать соответствующую часть спецификации, с добавлен акцент:

Обычный символ - это шаблон, который должен соответствовать самому себе. Он может быть любым символом в поддерживаемом наборе символов, кроме NUL, эти специальные символы оболочки в Цитата, которая требует цитирования, и следующие три специальных символа шаблона. Согласование должно основываться на битовой схеме, используемой для кодирования символа, а не на графическом представлении символа. Если какой-либо символ (обычный, специальная оболочка или специальный шаблон) цитируется, этот шаблон должен соответствовать самому символу. Специальные символы оболочки всегда требуют цитирования.

При некорректном и вне выражения скобки следующие три символа должны иметь особое значение в спецификации шаблонов:

  • ? - вопросительный знак - это шаблон, который должен соответствовать любому символу.
  • * - Звездочка - это шаблон, который должен соответствовать нескольким символам, как описано в Шаблоны, соответствующие нескольким символам.
  • [ - Открытая скобка должна ввести выражение скобки шаблона.

Таким образом, стандарт явно требует любого символа, отличного от NUL, кроме ?, * или [ или тех, которые перечислены в другом месте, так как требуется, чтобы кавычки соответствовали самим себе. bash поведение по умолчанию extglob позволяет ему соответствовать этому стандарту в конфигурации по умолчанию.


Однако для ваших собственных скриптов и вашей собственной интерактивной оболочки, если у вас нет привычки запускать код, написанный для POSIX sh с необычными шаблонами, рекомендуется делать extglob.

Ответ 2

Будучи человеком Kornshell, у меня есть extglob в моем .bashrc по умолчанию, потому что так оно и есть в Kornshell, и я использую его много.

Например:

$ find !(target) -name "*.xml"

В Корншелле это не проблема. В BASH мне нужно установить extglob. Я также установил lithist и set -o vi. Это позволяет мне использовать команды VI в использовании моей истории оболочек, и когда я нажимаю v, он показывает мой код как кучу строк.

Без lithist установите:

for i in *;do;echo "I see $i";done

С listhist установите:

for i in *
do
    echo "I see $i"
done

Теперь, только если BASH имеет оператор print, я бы все установил.