В настоящее время у меня есть следующее регулярное выражение:
^\s*(.+)(?:[-\._ ]+)(\d+)\s*[xX]\s*(\d+)
Это будет соответствовать show_3x01_ep. name
и извлекать show
, 3
, 01
. Я хотел бы расширить это, чтобы можно было снимать несколько эпизодов. Например:
show _3x01_3x02 ep. name
Должен вернуться:
show, 3, 01, 3, 02
Не мог бы кто-нибудь объяснить мне, как это можно сделать?
3 ответа
Вы слишком многого ожидаете от своего регулярного выражения. Самый простой способ - сделать это в два этапа.
Прежде всего, обратите внимание, что (.+)
, который соответствует show
в вашем примере, является слишком общим. Если вы примените шаблон к show _3x01_3x02 ep. name
, вы получите show
- с завершающим пробелом - потому что следующий [-._ ]+
(нет необходимости экранировать точку или заключать класс символов в (?: ... )
) удовлетворяется только одним символом.
Это сделает то, о чем вы просите. Он находит первую строку буквенных символов, а затем все пары строк цифр, которые разделены одним x
.
use strict;
use warnings;
my $s = 'show _3x01_3x02 ep. name';
if ( my ($prefix) = $s =~ /([a-z]+)/i ) {
print "$prefix\n";
print "$1 $2\n" while $s =~ /(\d+)x(\d+)/g;
}
вывод
show
3 01
3 02
Используйте модификатор Perl g
Вы можете использовать Perl-модификатор регулярного выражения g для поиска шаблона более одного раза в строке. Затем вы можете сохранить эти совпадения в списке, а затем что-то сделать с этим списком или его отдельными элементами. Например:
$ echo 'show _3x01_3x02 ep.name' |
perl -ne '@words = ($_ =~ /\A(.*?)(?=\d)|(\d+)x(\d+)/g);
@words = grep { $_ ne "" } @words;
while (my $idx = each @words) {
@words[$idx] =~ s/^\s+|\s+\b|_//g;
};
print join(", ", @words), "\n"'
show, 3, 01, 3, 02
Вместо этого используйте String # scan в Ruby
Ваши имена файлов не совпадают, поэтому вам, вероятно, лучше просканировать известные шаблоны, а затем очистить. Я уже предоставил решение Perl, но предлагаю это решение Ruby в качестве альтернативы. Например:
str = 'show _3x01_3x02 ep. name'
str.scan(/\A(.*?)(?=\d)|(\d+)x(\d+)/).
flatten.compact.map { |e| e.gsub(?_, ' ').strip }
#=> ["show", "3", "01", "3", "02"]
В этой единственной строке кода много чего происходит, но это должно быть достаточно легко для понимания. Код будет:
- Сопоставьте все от начала строки до первой цифры в названии шоу.
- Сопоставьте все пары сезона / эпизода, которые он сможет найти.
- Вернуть все совпадения в виде массива.
- Сглаживайте вложенные массивы, созданные группами захвата, и отбрасывайте ноль.
- Замените подчеркивания пробелами в каждом элементе массива.
- Удаляет любые окружающие пробелы из каждого члена массива.
- Верните массив.
Само регулярное выражение совместимо с Perl, но остальная логика опирается на String # scan и другие внутренние компоненты, которые могут не отображаться непосредственно на Perl. YMMV.
Похожие вопросы
Новые вопросы
regex
Регулярные выражения предоставляют декларативный язык для сопоставления шаблонов в строках. Они обычно используются для проверки строк, разбора и преобразования. Укажите язык (PHP, Python и т. д.) или инструмент (grep, VS Code, Google Analytics и т. д.), который вы используете. Не размещайте вопросы, требующие объяснения того, что означает символ или чему будет соответствовать конкретное регулярное выражение.