Подтвердить что ты не робот

Regex для разбора каталога и имени файла

Я пытаюсь написать регулярное выражение, которое будет анализировать каталог и имя файла для полного пути, используя соответствующие группы.

так...

/var/log/xyz/10032008.log

распознает group 1 to be "/var/log/xyz" и group 2 to be "10032008.log"

Кажется простым, но я не могу заставить соответствующие группы работать для меня.

ПРИМЕЧАНИЕ. Как отмечают некоторые респонденты, это, вероятно, не очень хорошо использует регулярные выражения. Обычно я бы предпочел использовать API-интерфейс файла, который я использовал. То, что я на самом деле пытаюсь сделать, немного сложнее, чем это, но было бы гораздо труднее объяснить, поэтому я выбрал домен, с которым все будут знакомы, чтобы наиболее кратко описать проблему с корнем.

4b9b3361

Ответ 1

Попробуйте следующее:

^(.+)/([^/]+)$

Ответ 2

В языках, поддерживающих регулярные выражения с группами, не связанными с захватом:

((?:[^/]*/)*)(.*)

Я объясню 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

Пример

Чтобы проверить регулярное выражение, я использовал следующий Perl script...

#!/usr/bin/perl -w

use strict;
use warnings;

sub test {
  my $str = shift;
  my $testname = shift;

  $str =~ m#((?:[^/]*/)*)(.*)#;

  print "$str -- $testname\n";
  print "  1: $1\n";
  print "  2: $2\n\n";
}

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

Ответ 3

В большинстве языков есть функции синтаксического анализа пути, которые дадут вам это уже. Если у вас есть такая возможность, я бы рекомендовал использовать то, что приходит к вам бесплатно из коробки.

Предполагая, что/является ограничителем пути...

^(.*/)([^/]*)$

Первой группой будет любая информация о каталоге/пути, вторая будет именем файла. Например:

  • /foo/bar/baz.log: "/foo/bar/" - это путь, "baz.log" - это файл
  • foo/bar.log: "foo/" - это путь, "bar.log" - это файл
  • /foo/bar: "/foo/" - это путь, "bar" - это файл
  • /foo/bar/: "/foo/bar/" - это путь, и файл отсутствует.

Ответ 4

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

Если вы должны:

^(.*)/([^/]*)$

дает вам две части, которые вы хотели. Вам может потребоваться указать круглые скобки:

^\(.*\)/\([^/]*\)$

в зависимости от вашего предпочтительного синтаксиса языка.

Но я предлагаю вам просто использовать функцию поиска строки на языке, которая находит последний символ "/" и разбивает строку на этот индекс.

Ответ 5

Как насчет этого?

[/]{0,1}([^/]+[/])*([^/]*)

Детерминистский:

((/)|())([^/]+/)*([^/]*)

Строгий:

^[/]{0,1}([^/]+[/])*([^/]*)$
^((/)|())([^/]+/)*([^/]*)$

Ответ 6

Попробуйте следующее:

/^(\/([^/]+\/)*)(.*)$/

Он оставит конечную косую черту на пути.

Ответ 7

Очень поздний ответ, но надеюсь, что это поможет

^(.+?)/([\w]+\.log)$

Это использует ленивый чек для /, и я только что изменил принятый ответ

http://regex101.com/r/gV2xB7/1

Ответ 8

Обоснование:

Я провел небольшое исследование методом проб и ошибок. Выяснилось, что все значения, доступные на клавиатуре, могут быть файлом или каталогом, кроме '/' в * 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>.+))/

enter image description here

Шаг 2: Попробуйте найти первый каталог.

Затем каталог и его дочерний элемент всегда разделяются /. И имя каталога может быть любым, кроме /. Пусть сначала совпадут /var/.

/(?P<filepath>(?P<first_directory>(?P<root>[/]?)[^\/]+/)(?P<rest_of_the_path>.+))/

enter image description here

Шаг 3: Получить полный путь к каталогу для файла

Далее пусть совпадут все каталоги

/(?P<filepath>(?P<dir>(?P<root>[/]?)(?P<single_dir>[^\/]+/)+)(?P<rest_of_the_path>.+))/

enter image description here

Здесь single_dir - это yz/ потому что сначала он соответствовал var/, затем он обнаружил следующее вхождение того же шаблона, то есть log/, затем он обнаружил следующее вхождение того же шаблона yz/. Итак, это показало последнее появление паттерна.

Шаг 4: сопоставьте имя файла и очистите

Теперь мы знаем, что никогда не будем использовать такие группы, как single_dir, filepath, root. Поэтому позвольте это убрать.

Пусть держат их как группы, но не захватывают эти группы.

И rest_of_the_path - это просто имя файла! Итак, переименуйте его. И файл не будет иметь / в своем названии, поэтому лучше сохранить [^/]

/(?:(?P<dir>(?:[/]?)(?:[^\/]+/)+)(?P<filename>[^/]+))/

Это подводит нас к конечному результату. Конечно, есть несколько других способов сделать это. Я просто упоминаю один из способов здесь.

enter image description here

Правила Regex, используемые выше, перечислены здесь

^ означает, что строка начинается с
(?P<dir>pattern) означает захват группы по имени группы. У нас есть две группы с именем группы dir и file
(?:pattern) означает, что не следует рассматривать эту группу или группу без захвата.
? означает совпадение ноль или единицу. + означает совпадение с одним или несколькими [^\/] означает совпадение с любым символом кроме косой черты (/)

[/]? означает, что если это абсолютный путь, то он может начинаться с /, иначе не будет. Итак, сопоставьте ноль или одно вхождение /.

[^\/]+/ означает один или несколько символов, которые не являются косой чертой (/), за которой следует косая черта (/). Это будет соответствовать var/ или xyz/. Один каталог за раз.

Ответ 9

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