Bash
Совпадение шаблонов и регулярные выражения
Поиск…
Синтаксис
- $ shopt -u option # Деактивировать встроенную опцию Bash '
- $ shopt -s option # Активировать встроенную опцию Bash '
замечания
Классы символов
Допустимые классы символов для []
glob определяются стандартом POSIX:
alnum alpha ascii blank cntrl digit graph lower print punct space верхнее слово xdigit
Внутри []
может использоваться более одного класса или диапазона символов, например,
$ echo a[a-z[:blank:]0-9]*
будет соответствовать любому файлу, начинающемуся с a
и за ним следует либо строчная буква, либо пробел или цифра.
Следует иметь в виду, однако, что []
glob может быть полностью отвергнут, а не только его части. Отрицающая символ должен быть первым символом после открытия [
, например, это выражение соответствует всем файлам , которые не начинаются с a
$ echo [^a]*
Следующее соответствует всем файлам, начинающимся с цифры или ^
$ echo [[:alpha:]^a]*
Он не соответствует файлу или папке, которая начинается с буквы, кроме a
потому что ^
интерпретируется как литерал ^
.
Экранирование символов глобуса
Возможно, что файл или папка содержит символ глобуса как часть его имени. В этом случае glob может быть экранирован с предыдущим \
для того, чтобы выполнить литеральное совпадение. Другой подход заключается в использовании двойных ""
или одиночных ''
котировок для обращения к файлу. Bash не обрабатывает глобусы, которые заключены в ""
или ''
.
Отличие от регулярных выражений
Наиболее существенное различие между глобусами и регулярными выражениями состоит в том, что для правильных регулярных выражений требуется определитель, а также квантификатор. Квалификатор определяет, что нужно совместить, и квантификатор сообщает, как часто соответствовать определителю. Эквивалентный RegEx для *
glob есть .*
Где .
обозначает любой символ и *
обозначает ноль или более совпадений предыдущего символа. Эквивалентный RegEx для ?
glob .{1}
. Как и раньше, определитель .
соответствует любому символу, а {1}
указывает, что он соответствует предыдущему квалификатору ровно один раз. Это не следует путать с ?
квантификатор, который соответствует нулю или один раз в RegEx. Шаблон []
glob можно использовать точно так же в RegEx, если за ним следует обязательный квантификатор.
Эквивалентные регулярные выражения
Glob | RegEx |
---|---|
* | .* |
? | . |
[] | [] |
Проверьте, соответствует ли строка регулярному выражению
Проверьте, состоит ли строка в точности 8 цифр:
$ date=20150624
$ [[ $date =~ ^[0-9]{8}$ ]] && echo "yes" || echo "no"
yes
$ date=hello
$ [[ $date =~ ^[0-9]{8}$ ]] && echo "yes" || echo "no"
no
* Glob
подготовка
$ mkdir globbing
$ cd globbing
$ mkdir -p folder/{sub,another}folder/content/deepfolder/
touch macy stacy tracy "file with space" folder/{sub,another}folder/content/deepfolder/file .hiddenfile
$ shopt -u nullglob
$ shopt -u failglob
$ shopt -u dotglob
$ shopt -u nocaseglob
$ shopt -u extglob
$ shopt -u globstar
Звездочка *, вероятно, является наиболее часто используемым шаром. Он просто соответствует любой строке
$ echo *acy
macy stacy tracy
Единый * не будет соответствовать файлам и папкам, которые находятся в подпапках
$ echo *
emptyfolder folder macy stacy tracy
$ echo folder/*
folder/anotherfolder folder/subfolder
** glob
подготовка
$ mkdir globbing
$ cd globbing
$ mkdir -p folder/{sub,another}folder/content/deepfolder/
touch macy stacy tracy "file with space" folder/{sub,another}folder/content/deepfolder/file .hiddenfile
$ shopt -u nullglob
$ shopt -u failglob
$ shopt -u dotglob
$ shopt -u nocaseglob
$ shopt -u extglob
$ shopt -s globstar
Bash способен интерпретировать две соседние звездочки как единый глобус. При globstar
опции globstar
это можно использовать для соответствия папкам, которые находятся глубже в структуре каталогов
echo **
emptyfolder folder folder/anotherfolder folder/anotherfolder/content folder/anotherfolder/content/deepfolder folder/anotherfolder/content/deepfolder/file folder/subfolder folder/subfolder/content folder/subfolder/content/deepfolder folder/subfolder/content/deepfolder/file macy stacy tracy
**
можно думать о расширении пути, независимо от того, насколько глубока траектория. Этот пример соответствует любому файлу или папке, которая начинается с deep
, независимо от того, насколько глубоко он вложен:
$ echo **/deep*
folder/anotherfolder/content/deepfolder folder/subfolder/content/deepfolder
? шарик
подготовка
$ mkdir globbing
$ cd globbing
$ mkdir -p folder/{sub,another}folder/content/deepfolder/
touch macy stacy tracy "file with space" folder/{sub,another}folder/content/deepfolder/file .hiddenfile
$ shopt -u nullglob
$ shopt -u failglob
$ shopt -u dotglob
$ shopt -u nocaseglob
$ shopt -u extglob
$ shopt -u globstar
?
просто соответствует одному символу
$ echo ?acy
macy
$ echo ??acy
stacy tracy
[] Glob
подготовка
$ mkdir globbing
$ cd globbing
$ mkdir -p folder/{sub,another}folder/content/deepfolder/
touch macy stacy tracy "file with space" folder/{sub,another}folder/content/deepfolder/file .hiddenfile
$ shopt -u nullglob
$ shopt -u failglob
$ shopt -u dotglob
$ shopt -u nocaseglob
$ shopt -u extglob
$ shopt -u globstar
Если необходимо сопоставить определенные символы, тогда можно использовать «[]». Любой символ внутри '[]' будет сопоставляться ровно один раз.
$ echo [m]acy
macy
$ echo [st][tr]acy
stacy tracy
[]
Glob, однако, более универсален, чем просто. Он также допускает отрицательное совпадение и даже совпадение диапазонов символов и характеристик. Отрицательный результат достигается при использовании !
или ^
как первый символ, следующий за [
. Мы можем соответствовать stacy
по
$ echo [!t][^r]acy
stacy
Здесь мы говорим bash, что хотим сопоставлять только файлы, которые не начинаются с t
а вторая буква не является r
а файл заканчивается acy
.
Диапазоны могут быть сопоставлены путем разделения пары символов с дефисом ( -
). Любой символ, который попадает между этими двумя охватывающими символами - включительно - будет соответствовать. Например, [rt]
эквивалентно [rst]
$ echo [r-t][r-t]acy
stacy tracy
Классы символов могут быть сопоставлены с помощью [:class:]
, например, чтобы соответствовать файлам, содержащим пробелы
$ echo *[[:blank:]]*
file with space
Сопряжение скрытых файлов
подготовка
$ mkdir globbing
$ cd globbing
$ mkdir -p folder/{sub,another}folder/content/deepfolder/
touch macy stacy tracy "file with space" folder/{sub,another}folder/content/deepfolder/file .hiddenfile
$ shopt -u nullglob
$ shopt -u failglob
$ shopt -u dotglob
$ shopt -u nocaseglob
$ shopt -u extglob
$ shopt -u globstar
Встроенная опция dotglob Bash позволяет сопоставлять скрытые файлы и папки, то есть файлы и папки, начинающиеся с .
$ shopt -s dotglob
$ echo *
file with space folder .hiddenfile macy stacy tracy
Нечувствительность к регистру
подготовка
$ mkdir globbing
$ cd globbing
$ mkdir -p folder/{sub,another}folder/content/deepfolder/
touch macy stacy tracy "file with space" folder/{sub,another}folder/content/deepfolder/file .hiddenfile
$ shopt -u nullglob
$ shopt -u failglob
$ shopt -u dotglob
$ shopt -u nocaseglob
$ shopt -u extglob
$ shopt -u globstar
Установка параметра nocaseglob
будет соответствовать nocaseglob
нечувствительным к регистру
$ echo M*
M*
$ shopt -s nocaseglob
$ echo M*
macy
Поведение, когда glob ничего не соответствует
подготовка
$ mkdir globbing
$ cd globbing
$ mkdir -p folder/{sub,another}folder/content/deepfolder/
touch macy stacy tracy "file with space" folder/{sub,another}folder/content/deepfolder/file .hiddenfile
$ shopt -u nullglob
$ shopt -u failglob
$ shopt -u dotglob
$ shopt -u nocaseglob
$ shopt -u extglob
$ shopt -u globstar
Если glob ничего не соответствует, результат определяется опциями nullglob
и failglob
. Если ни один из них не задан, Bash вернет сам глобус, если ничего не согласовано
$ echo no*match
no*match
Если nullglob
активирован, то ничего ( null
) не возвращается:
$ shopt -s nullglob
$ echo no*match
$
Если failglob
активирован, возвращается сообщение об ошибке:
$ shopt -s failglob
$ echo no*match
bash: no match: no*match
$
Обратите внимание, что параметр failglob
заменяет параметр nullglob
, т. nullglob
Если nullglob
и failglob
оба установлены, тогда - в случае отсутствия соответствия - возвращается ошибка.
Расширенное подтягивание
подготовка
$ mkdir globbing
$ cd globbing
$ mkdir -p folder/{sub,another}folder/content/deepfolder/
touch macy stacy tracy "file with space" folder/{sub,another}folder/content/deepfolder/file .hiddenfile
$ shopt -u nullglob
$ shopt -u failglob
$ shopt -u dotglob
$ shopt -u nocaseglob
$ shopt -u extglob
$ shopt -u globstar
extglob
опция extglob
позволяет расширить возможности glob
shopt -s extglob
Следующие под-шаблоны содержат действительные расширенные глобусы:
-
?(pattern-list)
- Соответствует нулю или одному вхождению данных шаблонов -
*(pattern-list)
- соответствует нулю или больше вхождений данных шаблонов -
+(pattern-list)
- соответствует одному или нескольким вхождениям данных шаблонов -
@(pattern-list)
- соответствует одному из заданных шаблонов -
!(pattern-list)
- Совпадает со всем, кроме одного из заданных шаблонов
Список pattern-list
- это список глобусов, разделенных символом |
,
$ echo *([r-t])acy
stacy tracy
$ echo *([r-t]|m)acy
macy stacy tracy
$ echo ?([a-z])acy
macy
Сам pattern-list
может быть другим, вложенным расширенным глобусом. В приведенном выше примере мы видели, что мы можем сопоставить tracy
и stacy
с *(rt)
. Этот расширенный сам глобус можно использовать внутри отрицаемого расширенного глоба !(pattern-list)
, чтобы соответствовать macy
$ echo !(*([r-t]))acy
macy
Он соответствует любому, что не начинается с нуля или более вхождений букв r
, s
и t
, что оставляет только macy
как возможное совпадение.
Соответствие регулярных выражений
pat='[^0-9]+([0-9]+)'
s='I am a string with some digits 1024'
[[ $s =~ $pat ]] # $pat must be unquoted
echo "${BASH_REMATCH[0]}"
echo "${BASH_REMATCH[1]}"
Выход:
I am a string with some digits 1024
1024
Вместо назначения регулярного выражения переменной ( $pat
) мы могли бы также:
[[ $s =~ [^0-9]+([0-9]+) ]]
объяснение
- Конструкция
[[ $s =~ $pat ]]
выполняет сопоставление регулярных выражений - Захваченные группы, т. Е. Результаты совпадения, доступны в массиве с именем BASH_REMATCH
- 0-й индекс в массиве BASH_REMATCH - это полное совпадение
- I-й индекс в массиве BASH_REMATCH - это i-я захваченная группа, где i = 1, 2, 3 ...
Получить захваченные группы из регулярного выражения для строки
a='I am a simple string with digits 1234'
pat='(.*) ([0-9]+)'
[[ "$a" =~ $pat ]]
echo "${BASH_REMATCH[0]}"
echo "${BASH_REMATCH[1]}"
echo "${BASH_REMATCH[2]}"
Выход:
I am a simple string with digits 1234
I am a simple string with digits
1234