Intereting Posts
Оказывает ли система X-оконной системы масштабируемость? Как распаковать источник libc6 на Hardy, используя debian / rules? Grub возвращает Файл не найден при загрузке на новый диск с Debian Jessie Параметр -cp для команды java Почему одна из этих команд даты действительна, а другая нет? Время выполнения и ресурсы после процессов, которые выполнялись так долго Каталог «~» попал в одну из моих папок Как вы можете вставлять рисунки с разным размером? Veritus Volume Manager perl недоступен Как настроить Linux для кэширования метаданных файлов в соответствии с содержанием? Multipath для логического тома в промежуточной виртуальной машине Поддержка vmxnet3 multiqueue в рабочей станции VMware Когда был создан файл DHCP-сервер со статическим IP-адресом, не разрешающим имена хостов (клиенты делают) Завершение Bash не будет работать, если вы вызываете приложение с абсолютным путем

История Бэша

Существует ли историческая причина того, почему Bash «globbing» и регулярные выражения не идентичны? Например, я считаю, что в Bash [1-2]* соответствует все, что начинается с 1 или 2, за которым следует что-то еще, тогда как в качестве регулярного выражения [1-2]* будет соответствовать только последовательность из 1s и 2s. Мои скрипты Bash и REGEX foo очень слабы, и я регулярно сталкиваюсь с проблемами, связанными с этими различиями, из-за которых мне было любопытно, почему они разные.

bash был первоначально разработан в конце 80-х как частичный клон ksh с некоторыми интерактивными функциями csh / tcsh.

Истоки глобуса должны быть найдены в тех ранних оболочках, на которых он опирается.

Сам ksh является продолжением оболочки Борна. Сама оболочка Bourne (впервые выпущенная в 1979 году в Unix V7) была чистой реализацией с нуля, но она полностью не отходила от оболочки Thompson (оболочка V1 -> V6) и включала в себя функции из оболочки Mashey.

В частности, аргументы команды по-прежнему разделялись пробелами, | был теперь новым оператором трубы, но ^ прежнему поддерживался в качестве альтернативы (а также объясняет, почему вы делаете [!az] а не [^az] ), $1 все еще был первым аргументом для скрипта, а обратная косая черта по-прежнему была символом escape. Так много операторов регулярного выражения ( ^\|$ ) имеют особое значение в оболочке.

Корпус Thompson полагался на внешнюю утилиту для подгонки. Когда sh найден некорректно * , [ или ? s в команде, он будет запускать команду через glob .

 rm *.txt 

в конечном итоге будет работать как:

 ["glob", "rm", "*.txt"] 

и glob закончит работать с rm со списком файлов, соответствующих этому шаблону.

 grep a.\*b *.txt 

будет запускать glob как:

 ["glob", "grep", "a.\252b", "*.txt"] 

Вышеуказанный * был указан, установив 8-й бит на этот символ, не позволяя glob рассматривать его как шаблон. glob затем удалит этот бит перед вызовом grep .

Чтобы сделать эквивалент с регулярными выражениями, это было бы:

 regexp rm '\.txt$' 

Или:

 regexp rm '^[^.].*\.txt$' 

для исключения точечных файлов.

Необходимо избегать операторов, поскольку они удваиваются как специальные символы оболочки, тот факт . , обычным в именах файлов является оператор регулярного выражения, что делает его не очень подходящим для соответствия именам файлов и сложным для новичков. В большинстве случаев все, что вам нужно, это подстановочные знаки, которые могут заменить либо одно ( ? ), Либо любое число ( * ) символов.

Теперь разные оболочки добавили разные операторы глобулизации. В настоящее время ksh и zsh globs (и в некоторой степени bash -O extglob который реализует подмножество ksh globs) функционально эквивалентны регулярным выражениям с синтаксисом, который является менее громоздким для использования с именами файлов и текущим синтаксисом оболочки. Например, в zsh (с расширением extendedglob) вы можете:

 echo a#.txt 

если вы хотите (маловероятно) совместить имена файлов, которые состоят из последовательностей a за которыми следует .txt . Легче, чем echo (^a*\.txt$) (здесь использование фигурных скобок как способ изолировать операторы регулярных выражений от операторов оболочки, которые могли быть односторонними оболочками, может справиться с ним).

 echo (foo|bar|<1-20>).(#i)mpg 

Для файлов mpg (без учета регистра), чье базовое имя – foo, bar или десятичное число от 1 до 20 …

ksh93 теперь также может включать регулярные выражения (базовые, расширенные, perl-like или «дополненные») в своих глобах (хотя это довольно сложно) и даже предоставляет инструмент для преобразования между glob и regexp ( printf %R , printf %P ):

 echo ~(Ei:.*\.txt) 

для сопоставления (не скрытых) файлов txt с регулярными выражениями E xtended, case- i nsensitively.

Регулярные языки были введены Клине в 1956 году. В оригинальной работе не было полной современной записи для регулярных выражений, но она вводила «звезду Клин»: A* означает «любое количество повторений A ». В следующем десятилетии появились, в частности, более или менее стандартные обозначения . для произвольного символа и ? означает, что предыдущий символ является необязательным.

Обозначение глобуса Bash проистекает из команды glob введенной полностью обратно в Unix v1 в 1971 году. В то время, подглаживание выполнялось отдельной программой; позже он был перенесен в оболочку. У команды раннего glob есть ? означает «любой символ» и * означает «любая последовательность символов». Я не знаю, почему были выбраны персонажи; ? довольно интуитивно понятен, и * возможно, был вдохновлен одним из регулярных выражений.

Глобблинг не должен был быть таким же общим, как регулярные выражения, и регулярные выражения в то время не были широко распространены, поэтому не было призыва к унификации понятий. С самого начала существовали синтаксические несовместимости, с ? , . и * означает разные вещи в шаблонах имен файлов и в регулярных выражениях.

Современные оболочки, такие как bash, расширяются по шаблонам глобуса, но это постепенная эволюция, поддерживающая обратную совместимость. Ksh88 (версия оболочки Korn 1988 года) ввел расширенный синтаксис шаблонов оболочки, который не мог быть того же синтаксиса, что и обычные регулярные выражения, но был сильно вдохновлен им: *(PATTERN) означает любое количество повторений PATTERN , @(PATTERN1|PATTERN2) означает « PATTERN1 или PATTERN2 » и т. Д.

Современные версии bash (начиная с версии 2.02) поддерживают расширенные шаблоны ksh88, если вы shopt -s extglob .

Историческая причина: ДА. Справка:
http://en.wikipedia.org/wiki/Glob_(programming)#Origin

Чтобы продемонстрировать расхождение, вот хороший и простой пример: a*

  • shell globbing: значение есть, первый символ – a а затем все (a, ab, abca …)
  • regex: значение равно нулю или больше повторений символа a (a, aa, aaa …)

Я с готовностью соглашаюсь с тем, что это несоответствие в значении очень запутанно для новых пользователей.

Глобус, возможно, легче понять для новичков, но это также менее мощная конструкция.