Вопрос:
Я пытаюсь написать регулярное выражение, которое будет анализировать каталог и имя файла для полного пути, используя соответствующие группы.
так…
/var/log/xyz/10032008.log
распознает group 1 to be «/var/log/xyz» и group 2 to be «10032008.log»
Кажется простым, но я не могу заставить соответствующие группы работать для меня.
ПРИМЕЧАНИЕ. Как отмечают некоторые респонденты, это, вероятно, не очень хорошо использует регулярные выражения. Обычно я бы предпочел использовать API-интерфейс файла, который я использовал. То, что я на самом деле пытаюсь сделать, немного сложнее, чем это, но было бы гораздо труднее объяснить, поэтому я выбрал домен, с которым все будут знакомы, чтобы наиболее кратко описать проблему с корнем.
Лучший ответ:
Попробуйте следующее:
^(.+)/([^/]+)$ Ответ №1
В языках, поддерживающих регулярные выражения с группами, не связанными с захватом:
((?:[^/]*/)*)(.*)
Я объясню gnarly regex, взорв его…
( (?: [^/]* / ) * ) (.*)
Что означают части:
( — capture group 1 starts (?: — non-capturing group starts [^/]* — greedily match as many non-directory separators as possible / — match a single directory-separator character ) — non-capturing group ends * — repeat the non-capturing group zero-or-more times ) — capture group 1 ends (.*) — capture all remaining characters in group 2 Содержание
- Пример
- Обоснование:
- результат
- Шаг за шагом процесс создания регулярного выражения
- Шаблон Объяснение
- Шаг 1: Начните с соответствия root каталога
- Шаг 2: Попробуйте найти первый каталог.
- Шаг 3: Получить полный путь к каталогу для файла
- Шаг 4: сопоставьте имя файла и очистите
- Правила Regex, используемые выше, перечислены здесь
- Пример
- Обоснование:
- результат
- Шаг за шагом процесс создания регулярного выражения
- Шаблон Объяснение
- Шаг 1: Начните с соответствия root каталога
- Шаг 2: Попробуйте найти первый каталог.
- Шаг 3: Получить полный путь к каталогу для файла
- Шаг 4: сопоставьте имя файла и очистите
- Правила Regex, используемые выше, перечислены здесь
Пример
Чтобы проверить регулярное выражение, я использовал следующий Perl script…
#!/usr/bin/perl -w use strict; use warnings; sub test { my $str = shift; my $testname = shift; $str =~ m#((?:[^/]*/)*)(.*)#; print «$str — $testnamen»; print » 1: $1n»; print » 2: $2nn»; } test(‘/var/log/xyz/10032008.log’, ‘absolute path’); test(‘var/log/xyz/10032008.log’, ‘relative path’); test(‘10032008.log’, ‘filename-only’); test(‘/10032008.log’, ‘file directly under root’);
Вывод script…
/var/log/xyz/10032008.log — absolute path 1: /var/log/xyz/ 2: 10032008.log var/log/xyz/10032008.log — relative path 1: var/log/xyz/ 2: 10032008.log 10032008.log — filename-only 1: 2: 10032008.log /10032008.log — file directly under root 1: / 2: 10032008.log Ответ №2
В большинстве языков есть функции синтаксического анализа пути, которые дадут вам это уже. Если у вас есть такая возможность, я бы рекомендовал использовать то, что приходит к вам бесплатно из коробки.
Предполагая, что/является ограничителем пути…
^(.*/)([^/]*)$
Первой группой будет любая информация о каталоге/пути, вторая будет именем файла. Например:
- /foo/bar/baz.log: “/foo/bar/” – это путь, “baz.log” – это файл
- foo/bar.log: “foo/” – это путь, “bar.log” – это файл
- /foo/bar: “/foo/” – это путь, “bar” – это файл
- /foo/bar/: “/foo/bar/” – это путь, и файл отсутствует.
Ответ №3
Какой язык? и зачем использовать регулярное выражение для этой простой задачи?
Если вы должны:
^(.*)/([^/]*)$
дает вам две части, которые вы хотели. Вам может потребоваться указать круглые скобки:
^(.*)/([^/]*)$
в зависимости от вашего предпочтительного синтаксиса языка.
Но я предлагаю вам просто использовать функцию поиска строки на языке, которая находит последний символ “/” и разбивает строку на этот индекс.
Ответ №4
Как насчет этого?
[/]{0,1}([^/]+[/])*([^/]*)
Детерминистский:
((/)|())([^/]+/)*([^/]*)
Строгий:
^[/]{0,1}([^/]+[/])*([^/]*)$ ^((/)|())([^/]+/)*([^/]*)$ Ответ №5
Попробуйте следующее:
/^(/([^/]+/)*)(.*)$/
Он оставит конечную косую черту на пути.
Ответ №6
Очень поздний ответ, но надеюсь, что это поможет
^(.+?)/([w]+.log)$
Это использует ленивый чек для /, и я только что изменил принятый ответ
http://regex101.com/r/gV2xB7/1
Ответ №7
Обоснование:
Я провел небольшое исследование методом проб и ошибок. Выяснилось, что все значения, доступные на клавиатуре, могут быть файлом или каталогом, кроме ‘/’ в * nux machine.
Я использовал команду touch, чтобы создать файл для следующих символов, и он создал файл.
(Значения, разделенные запятыми ниже)
‘!’, ‘@’, ‘#’, ‘$’, “‘”,’% ‘,’ ^ ‘,’ & ‘,’ * ‘,’ (‘,’) ‘,’ ‘,’ “‘, ‘’, ‘-‘, ‘,’, ‘[‘, ‘]’, ‘{‘, ‘}’, ” ‘,’ ~ ‘,’> ‘,’ <‘,’ = ‘,’ + ‘,’; ‘,’: ‘,’ | ‘
Это не удалось, только когда я попытался создать ‘/’ (потому что это корневой каталог) и имя файла контейнера / потому что это разделитель файлов.
И это изменило время модификации текущего каталога . когда я touch. , Однако file.log возможен.
И, конечно же, az, AZ, 0-9, — (hypen), _ (подчеркивание) должны работать.
результат
Итак, по приведенным выше рассуждениям мы знаем, что имя файла или имя каталога может содержать все, кроме косой черты / forward. Таким образом, наше регулярное выражение будет получено из того, что не будет присутствовать в имени файла/имени каталога.
/(?:(?P<dir>(?:[/]?)(?:[^/]+/)+)(?P<filename>[^/]+))/
Шаг за шагом процесс создания регулярного выражения
Шаблон Объяснение
Шаг 1: Начните с соответствия root каталога
Каталог может начинаться с / когда он является абсолютным путем, и именем каталога, когда он относительный. Следовательно, ищите / с нуля или одного вхождения.
/(?P<filepath>(?P<root>[/]?)(?P<rest_of_the_path>.+))/
Шаг 2: Попробуйте найти первый каталог.
Затем каталог и его дочерний элемент всегда разделяются /. И имя каталога может быть любым, кроме /. Пусть сначала совпадут /var/.
/(?P<filepath>(?P<first_directory>(?P<root>[/]?)[^/]+/)(?P<rest_of_the_path>.+))/
Шаг 3: Получить полный путь к каталогу для файла
Далее пусть совпадут все каталоги
/(?P<filepath>(?P<dir>(?P<root>[/]?)(?P<single_dir>[^/]+/)+)(?P<rest_of_the_path>.+))/
Здесь single_dir – это yz/ потому что сначала он соответствовал var/, затем он обнаружил следующее вхождение того же шаблона, то есть log/, затем он обнаружил следующее вхождение того же шаблона yz/. Итак, это показало последнее появление паттерна.
Шаг 4: сопоставьте имя файла и очистите
Теперь мы знаем, что никогда не будем использовать такие группы, как single_dir, filepath, root. Поэтому позвольте это убрать.
Пусть держат их как группы, но не захватывают эти группы.
И rest_of_the_path – это просто имя файла! Итак, переименуйте его. И файл не будет иметь / в своем названии, поэтому лучше сохранить [^/]
/(?:(?P<dir>(?:[/]?)(?:[^/]+/)+)(?P<filename>[^/]+))/
Это подводит нас к конечному результату. Конечно, есть несколько других способов сделать это. Я просто упоминаю один из способов здесь.
Правила Regex, используемые выше, перечислены здесь
^ означает, что строка начинается с
(?P<dir>pattern) означает захват группы по имени группы. У нас есть две группы с именем группы dir и file
(?:pattern) означает, что не следует рассматривать эту группу или группу без захвата.
? означает совпадение ноль или единицу. + означает совпадение с одним или несколькими [^/] означает совпадение с любым символом кроме косой черты (/)
[/]? означает, что если это абсолютный путь, то он может начинаться с /, иначе не будет. Итак, сопоставьте ноль или одно вхождение /.
[^/]+/ означает один или несколько символов, которые не являются косой чертой (/), за которой следует косая черта (/). Это будет соответствовать var/ или xyz/. Один каталог за раз.
Ответ №8
Я бы не делал этого с регулярным выражением. Я хотел бы использовать ваш язык в качестве средства для анализа имен путей и использовать регулярное выражение только для поиска, для которого требуется его природа.