История Бэша

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

3 Solutions collect form web for “История Бэша”

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 …)

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

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

  • Почему читать -r есть текст?
  • Массив Декартово произведение в bash
  • Завершить каждый фоновый процесс
  • shellcheck советует не использовать basename: почему?
  • Автозаполнение оболочки очень медленное после форматирования частичного диска
  • Почему моя программа «set» не выполняется?
  • Are & and; унарные или двоичные операторы?
  • Режим Vi или режим emacs во всей системе
  • Жареный зола PS1 не расширяется
  • xsel </ tmp / xselection не работает в скрипте
  • Преобразование рабочей команды в файл сценария оболочки, который получает аргументы
  • Interesting Posts

    общая файловая система с автономным доступом

    Программа для редактирования приложений по умолчанию (для типов MIME)

    tenshi и logfiles

    низкий уровень громкости звука ALSA

    неиспользуемое пространство в моей файловой системе на ubuntu

    Почему расширение файла работает для имен файлов с символом новой строки?

    Что мне нужно сделать дополнительно, чтобы запустить X, чтобы не заканчиваться на черном экране?

    Как экспортировать / импортировать цветовую схему терминала Ubuntu 16.04

    Как создать каталог с '/' в unix?

    Удаленные файлы все еще используются: memfd: pulseaudio (pulsaudi), memfd: xshmfence (Xorg), / tmp / ib … (mysqld)

    Заменить первый столбец файла с помощью вывода команды

    Установите Flash-плеер без привилегий root в Iceweasel (Firefox)

    Клиент OpenVPN получает новый ip для каждой загрузки, как получить тот же адрес в x время ожидания?

    Одновременное выполнение нескольких команд

    Создайте tar-архив, разбитый на блоки максимального размера

    Linux и Unix - лучшая ОС в мире.