Фильтруйте папки с именем timestamp - сопоставление с образцом или сопоставление с регулярным выражением с помощью утилиты find
Я пишу общий сценарий оболочки, который отфильтровывает файлы на основе заданного регулярного выражения.
Мой сценарий оболочки:
files=$(find $path -name $regex)
В одном из случаев (для фильтрации) я хочу отфильтровать папки внутри каталога, имена папок имеют следующий формат:
20161128-20:34:33:432813246
YYYYMMDD-HH:MM:SS:NS
Я не могу прийти к правильному регулярному выражению.
Я могу получить путь к файлам внутри папки с помощью регулярных выражений '*data.txt'
, так как я знаю имя файла внутри него.
Но это дает мне полный путь к файлу, что-то вроде
/path/20161128-20:34:33:432813246/data.txt
То, что я хочу, это просто:
/path/20161128-20:34:33:432813246
Пожалуйста, помогите мне в определении правильного регулярного выражения для моего требования
НОТА:
Я знаю, как обрабатывать данные после
files=$(find $path -name $regex)
Но так как сценарий должен быть универсальным для многих случаев использования, мне нужно только правильное регулярное выражение, которое необходимо передать.
2 ответа
По POSIX,
find
"s-name
-path
Первичные (тесты) используют шаблоны (известные как подстановочные выражения, глобусы) для сопоставления имен файлов и путей (в то время как шаблоны и регулярные выражения связаны между собой, их синтаксис и возможности значительно различаются; короче говоря: шаблоны синтаксически проще, но гораздо менее мощны).-name
и сопоставляет шаблон с частью базового имени (простого имени файла) только входного пути-path
сопоставляет шаблон с полным путем (полным путем)
И GNU, и BSD/macOS
find
реализовать нестандартные расширения:-iname
а также-ipath
, которые работают как их совместимые со стандартом аналоги (на основе шаблонов), за исключением того, что они соответствуют без учета регистра.-regex
а также-iregex
тесты на совпадение путей по регулярному выражению (регулярное выражение).- Предостережение: обе реализации предлагают как минимум 2 диалекта регулярных выражений на выбор (
-E
активирует поддержку расширенных регулярных выражений в BSDfind
и GNUfind
позволяет выбирать из нескольких диалектов с-regextype
, но никакие два диалекта не являются абсолютно одинаковыми во всех двух реализациях - подробности смотрите внизу.
- Предостережение: обе реализации предлагают как минимум 2 диалекта регулярных выражений на выбор (
Если ваши имена папок следуют схеме именования фиксированной ширины, шаблон будет работать:
pattern='[0-9][0-9][0-9][0-9][0-9][0-9][0-9]-[0-9][0-9]:[0-9][0-9]:[0-9][0-9]:[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]'
Конечно, вы можете воспользоваться ярлыком, если не ожидаете ложных срабатываний:
pattern='[0-9]*-[0-9]?:[0-9]?:[0-9]?:[0-9]*'
Обратите внимание, как *
а также ?
в отличие от регулярных выражений, не являются символами дублирования (квантификаторами), которые относятся к предыдущему выражению, но сами по себе представляют любую последовательность символов (*
) или любой отдельный символ (?
).
Если мы соберем все это вместе:
files=$(find "$path" -type d -name "$pattern")
Важно заключить в кавычки ссылки на переменные, чтобы защитить их значения от нежелательных расширений оболочки, в частности, чтобы сохранить любые пробелы в пути и предотвратить преждевременное сглаживание оболочкой значения
$pattern
,Обратите внимание, что я добавил
-type d
ограничить соответствие каталогам (папкам), что повышает производительность.
Дополнительная справочная информация:
Ниже приведена матрица элементов регулярных выражений в GNU find
v4.6.0 / BSD find
как найдено в macOS 10.12.1:
GNU
find
функции перечислены по типам, поддерживаемым-regextype
вариант, сemacs
быть по умолчанию.- Обратите внимание, что несколько
posix-*
Именованные типы регулярных выражений являются неправильными в том смысле, что они поддерживают функции, выходящие за рамки полномочий POSIX.
- Обратите внимание, что несколько
BSD
find
функции перечисленыbasic
(используя опцию NO regex, которая подразумевает BRE со вкусом платформы) иextended
(используя опцию-E
, что подразумевает EREs со вкусом платформы).
Для кроссплатформенного использования, придерживаясь POSIX ERE (расширенные регулярные выражения) при использовании -regextype posix-extended
с GNU find
и используя -E
с BSD find
Это безопасно, но обратите внимание, что не все функции, которые вы можете ожидать, будут поддерживаться, особенно \b
, \<
/ \>
и ярлыки классов персонажей, такие как \d
,
=================== GNU find ===================
== REGEX FEATURE: \{\}
TYPE: awk: -
TYPE: egrep: -
TYPE: ed: ✓
TYPE: emacs: -
TYPE: gnu-awk: -
TYPE: grep: ✓
TYPE: posix-awk: -
TYPE: posix-basic: ✓
TYPE: posix-egrep: -
TYPE: posix-extended: -
TYPE: posix-minimal-basic: ✓
TYPE: sed: ✓
== REGEX FEATURE: {}
TYPE: awk: -
TYPE: egrep: ✓
TYPE: ed: -
TYPE: emacs: -
TYPE: gnu-awk: ✓
TYPE: grep: -
TYPE: posix-awk: ✓
TYPE: posix-basic: -
TYPE: posix-egrep: ✓
TYPE: posix-extended: ✓
TYPE: posix-minimal-basic: -
TYPE: sed: -
== REGEX FEATURE: \+
TYPE: awk: -
TYPE: egrep: -
TYPE: ed: ✓
TYPE: emacs: -
TYPE: gnu-awk: -
TYPE: grep: ✓
TYPE: posix-awk: -
TYPE: posix-basic: ✓
TYPE: posix-egrep: -
TYPE: posix-extended: -
TYPE: posix-minimal-basic: -
TYPE: sed: ✓
== REGEX FEATURE: +
TYPE: awk: ✓
TYPE: egrep: ✓
TYPE: ed: -
TYPE: emacs: ✓
TYPE: gnu-awk: ✓
TYPE: grep: -
TYPE: posix-awk: ✓
TYPE: posix-basic: -
TYPE: posix-egrep: ✓
TYPE: posix-extended: ✓
TYPE: posix-minimal-basic: -
TYPE: sed: -
== REGEX FEATURE: \b
TYPE: awk: -
TYPE: egrep: ✓
TYPE: ed: ✓
TYPE: emacs: ✓
TYPE: gnu-awk: ✓
TYPE: grep: ✓
TYPE: posix-awk: -
TYPE: posix-basic: ✓
TYPE: posix-egrep: ✓
TYPE: posix-extended: ✓
TYPE: posix-minimal-basic: ✓
TYPE: sed: ✓
== REGEX FEATURE: \< \>
TYPE: awk: -
TYPE: egrep: ✓
TYPE: ed: ✓
TYPE: emacs: ✓
TYPE: gnu-awk: ✓
TYPE: grep: ✓
TYPE: posix-awk: -
TYPE: posix-basic: ✓
TYPE: posix-egrep: ✓
TYPE: posix-extended: ✓
TYPE: posix-minimal-basic: ✓
TYPE: sed: ✓
== REGEX FEATURE: [:digit:]
TYPE: awk: ✓
TYPE: egrep: ✓
TYPE: ed: ✓
TYPE: emacs: -
TYPE: gnu-awk: ✓
TYPE: grep: ✓
TYPE: posix-awk: ✓
TYPE: posix-basic: ✓
TYPE: posix-egrep: ✓
TYPE: posix-extended: ✓
TYPE: posix-minimal-basic: ✓
TYPE: sed: ✓
== REGEX FEATURE: \d
TYPE: awk: -
TYPE: egrep: -
TYPE: ed: -
TYPE: emacs: -
TYPE: gnu-awk: -
TYPE: grep: -
TYPE: posix-awk: -
TYPE: posix-basic: -
TYPE: posix-egrep: -
TYPE: posix-extended: -
TYPE: posix-minimal-basic: -
TYPE: sed: -
== REGEX FEATURE: \s
TYPE: awk: ✓
TYPE: egrep: ✓
TYPE: ed: -
TYPE: emacs: ✓
TYPE: gnu-awk: ✓
TYPE: grep: -
TYPE: posix-awk: ✓
TYPE: posix-basic: -
TYPE: posix-egrep: ✓
TYPE: posix-extended: ✓
TYPE: posix-minimal-basic: -
TYPE: sed: -
=================== BSD find ===================
== REGEX FEATURE: \{\}
TYPE: basic: ✓
TYPE: extended: -
== REGEX FEATURE: {}
TYPE: basic: -
TYPE: extended: ✓
== REGEX FEATURE: \+
TYPE: basic: -
TYPE: extended: -
== REGEX FEATURE: +
TYPE: basic: -
TYPE: extended: ✓
== REGEX FEATURE: \b
TYPE: basic: -
TYPE: extended: -
== REGEX FEATURE: \< \>
TYPE: basic: -
TYPE: extended: -
== REGEX FEATURE: [:digit:]
TYPE: basic: ✓
TYPE: extended: ✓
== REGEX FEATURE: \d
TYPE: basic: -
TYPE: extended: -
== REGEX FEATURE: \s
TYPE: basic: -
TYPE: extended: ✓
Когда у вас есть полный путь к файлу, вам не нужно регулярное выражение для извлечения имени каталога.
dirname "/path/20161128-20:34:33:432813246/data.txt"
дам тебе
/path/20161128-20:34:33:432813246
Если вы действительно хотите регулярное выражение, попробуйте это:
\d{8}-\d{2}:\d{2}:\d{2}:\d{9}