Ответ 1
Попробуйте следующее:
^(.+)/([^/]+)$
Я пытаюсь написать регулярное выражение, которое будет анализировать каталог и имя файла для полного пути, используя соответствующие группы.
так...
/var/log/xyz/10032008.log
распознает group 1 to be "/var/log/xyz"
и group 2 to be "10032008.log"
Кажется простым, но я не могу заставить соответствующие группы работать для меня.
ПРИМЕЧАНИЕ. Как отмечают некоторые респонденты, это, вероятно, не очень хорошо использует регулярные выражения. Обычно я бы предпочел использовать API-интерфейс файла, который я использовал. То, что я на самом деле пытаюсь сделать, немного сложнее, чем это, но было бы гораздо труднее объяснить, поэтому я выбрал домен, с которым все будут знакомы, чтобы наиболее кратко описать проблему с корнем.
Попробуйте следующее:
^(.+)/([^/]+)$
В языках, поддерживающих регулярные выражения с группами, не связанными с захватом:
((?:[^/]*/)*)(.*)
Я объясню 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
В большинстве языков есть функции синтаксического анализа пути, которые дадут вам это уже. Если у вас есть такая возможность, я бы рекомендовал использовать то, что приходит к вам бесплатно из коробки.
Предполагая, что/является ограничителем пути...
^(.*/)([^/]*)$
Первой группой будет любая информация о каталоге/пути, вторая будет именем файла. Например:
Какой язык? и зачем использовать регулярное выражение для этой простой задачи?
Если вы должны:
^(.*)/([^/]*)$
дает вам две части, которые вы хотели. Вам может потребоваться указать круглые скобки:
^\(.*\)/\([^/]*\)$
в зависимости от вашего предпочтительного синтаксиса языка.
Но я предлагаю вам просто использовать функцию поиска строки на языке, которая находит последний символ "/" и разбивает строку на этот индекс.
Как насчет этого?
[/]{0,1}([^/]+[/])*([^/]*)
Детерминистский:
((/)|())([^/]+/)*([^/]*)
Строгий:
^[/]{0,1}([^/]+[/])*([^/]*)$
^((/)|())([^/]+/)*([^/]*)$
Попробуйте следующее:
/^(\/([^/]+\/)*)(.*)$/
Он оставит конечную косую черту на пути.
Очень поздний ответ, но надеюсь, что это поможет
^(.+?)/([\w]+\.log)$
Это использует ленивый чек для /
, и я только что изменил принятый ответ
Я провел небольшое исследование методом проб и ошибок. Выяснилось, что все значения, доступные на клавиатуре, могут быть файлом или каталогом, кроме '/' в * nux machine.
Я использовал команду touch, чтобы создать файл для следующих символов, и он создал файл.
(Значения, разделенные запятыми ниже)
'!', '@', '#', '$', "'",'% ',' ^ ',' & ',' * ',' (',') ',' ',' "', '\', '-', ',', '[', ']', '{', '}', '' ',' ~ ','> ',' <',' = ',' + ','; ',': ',' | '
Это не удалось, только когда я попытался создать '/' (потому что это корневой каталог) и имя файла контейнера /
потому что это разделитель файлов.
И это изменило время модификации текущего каталога .
когда я touch.
, Однако file.log возможен.
И, конечно же, az
, AZ
, 0-9
, -
(hypen), _
(подчеркивание) должны работать.
Итак, по приведенным выше рассуждениям мы знаем, что имя файла или имя каталога может содержать все, кроме косой черты /
forward. Таким образом, наше регулярное выражение будет получено из того, что не будет присутствовать в имени файла/имени каталога.
/(?:(?P<dir>(?:[/]?)(?:[^\/]+/)+)(?P<filename>[^/]+))/
root
каталога Каталог может начинаться с /
когда он является абсолютным путем, и именем каталога, когда он относительный. Следовательно, ищите /
с нуля или одного вхождения.
/(?P<filepath>(?P<root>[/]?)(?P<rest_of_the_path>.+))/
Затем каталог и его дочерний элемент всегда разделяются /
. И имя каталога может быть любым, кроме /
. Пусть сначала совпадут /var/.
/(?P<filepath>(?P<first_directory>(?P<root>[/]?)[^\/]+/)(?P<rest_of_the_path>.+))/
Далее пусть совпадут все каталоги
/(?P<filepath>(?P<dir>(?P<root>[/]?)(?P<single_dir>[^\/]+/)+)(?P<rest_of_the_path>.+))/
Здесь single_dir - это yz/
потому что сначала он соответствовал var/
, затем он обнаружил следующее вхождение того же шаблона, то есть log/
, затем он обнаружил следующее вхождение того же шаблона yz/
. Итак, это показало последнее появление паттерна.
Теперь мы знаем, что никогда не будем использовать такие группы, как single_dir, filepath, root. Поэтому позвольте это убрать.
Пусть держат их как группы, но не захватывают эти группы.
И rest_of_the_path - это просто имя файла! Итак, переименуйте его. И файл не будет иметь /
в своем названии, поэтому лучше сохранить [^/]
/(?:(?P<dir>(?:[/]?)(?:[^\/]+/)+)(?P<filename>[^/]+))/
Это подводит нас к конечному результату. Конечно, есть несколько других способов сделать это. Я просто упоминаю один из способов здесь.
^
означает, что строка начинается с (?P<dir>pattern)
означает захват группы по имени группы. У нас есть две группы с именем группы dir
и file
(?:pattern)
означает, что не следует рассматривать эту группу или группу без захвата. ?
означает совпадение ноль или единицу. +
означает совпадение с одним или несколькими [^\/]
означает совпадение с любым символом кроме косой черты (/
)
[/]?
означает, что если это абсолютный путь, то он может начинаться с /, иначе не будет. Итак, сопоставьте ноль или одно вхождение /
.
[^\/]+/
означает один или несколько символов, которые не являются косой чертой (/
), за которой следует косая черта (/
). Это будет соответствовать var/
или xyz/
. Один каталог за раз.
Я бы не делал этого с регулярным выражением. Я хотел бы использовать ваш язык в качестве средства для анализа имен путей и использовать регулярное выражение только для поиска, для которого требуется его природа.