Регулярное выражение Perl для строки и цифр — соответствует только последним 6 цифрам

#regex #perl

Вопрос:

Мне нужно извлечь последние 6 цифр из имени файла (это дата), и регулярное выражение для меня не работает.

Строка является: name_of_file0000000546210618.A001.6476871457

Мне нужно знать только это: name_of_file210618.A001

Мое регулярное выражение: name_of_file(d{6}).Ad{3} — не работает

Я тоже попробовал: name_of_file(d{6}).Ad{3} — не работает

Более подробная информация:

Мы уже использовали name_of_file(d{6}).Ad{3} его, и он работает уже более 3 лет. Строка в этих случаях справедлива name_of_file210618.A001.6476871457 , и регулярное выражение принимает только это: name_of_file210618.A001 . И это именно то, что мне нужно в данном случае, мне нужно обработать цифры раньше 210618 .

Комментарии:

1. Какой код вы используете?

2. d{6} соответствует только 6 цифрам, ( будет соответствовать буквальной открытой скобке. .Ad{3} соответствует 1 любому символу, буквенному «А», за которым следуют 3 цифры. Ничто из этого не соответствует вашей строке. Как ты думал, что это сработает?

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

4. @TLP, потому что мы уже используем его, и он работает более 3 лет: name_of_file(d{6}). Ad{3} и строка в этих случаях просто name_of_file210618.A001.6476871457 — и регулярное выражение принимает только это: name_of_file210618.A001 — и это именно то, что мне нужно в моем случае, мне нужно обработать цифры до 210618…

5. Из вопроса совсем не очевидно, что на chardigits самом деле означает «символ A , за которым следуют три цифры». Пожалуйста, приведите реальные примеры.

Ответ №1:

Тебе нужно

 name_of_fileKd*(?=d{6}.Ad{3})
 

Замените пустой строкой. Смотрите демонстрацию регулярных выражений. Подробные сведения:

  • name_of_file — определенная строка
  • K — оператор сброса соответствия отбрасывает текст, сопоставленный до сих пор, из общего буфера памяти соответствия
  • d* — ноль или более цифр
  • (?=d{6}.Ad{3}) — положительный внешний вид, для которого требуется шесть цифр, .A и три цифры должны появиться сразу справа от текущего местоположения.

Смотрите демо-версию Perl онлайн:

 #!/usr/bin/perl
use feature 'say';
use strict;
use warnings;
 
my $str = "name_of_file0000000546210618.A001.6476871457";
say $str =~ s/name_of_fileKd*(?=d{6}.Ad{3})//r;
 

Выход:

 name_of_file210618.A001.6476871457
 

Ответ №2:

Удалите все цифры, за которыми следуют 6 цифр:

 perl -pe 's/d*(?=d{6})//' <<< 'name_of_file0000000546210618.chardigits.digits'
 

Комментарии:

1. Поскольку операция изменила внешний вид строки, это больше не будет работать.

Ответ №3:

Причина, по которой ваше регулярное выражение

 name_of_file(d{6}).Ad{3}
#           ^^--- escaped parenthesis
 

Не работает, потому что он ожидает буквальную скобку ( в вашей строке. Поскольку их нет, это никогда не будет совпадать.

Это регулярное выражение

 name_of_file(d{6}).Ad{3} 
 

Не будет совпадать, так как вы «привязали» name_of_file его между и .A , без учета промежуточных символов.

Самое простое исправление, позволяющее добавить дополнительные номера наполнителя, — это просто добавить d* их перед областью захвата. Вы также должны бежать . , так как это метасимвол регулярного выражения, который означает «соответствует любому символу, кроме новой строки».

 name_of_filed*(d{6}).Ad{3}
 

Теперь это позволит регулярному выражению более свободно сопоставляться со строками, такими как

 name_of_file0000000546210618.A001.6476871457
#           ^^^^^^^^^^---- unneeded numbers
 

Аналогично, вы могли бы просто удалить привязку перед цифрами

 (d{6}).Ad{3}
 

Мне странно, что строка name_of_file находится в регулярном выражении. Если это заполнитель для фактического имени файла, это будет означать, что вы жестко кодируете имя файла в своем регулярном выражении, то есть оно будет соответствовать только этому точному имени файла и ничего больше. Обычно требуется, чтобы регексы соответствовали нескольким строкам разного типа. Я бы ожидал, что регулярное выражение, соответствующее разным именам файлов, будет выглядеть примерно так:

  [pL_] d*(d{6}).Ad{3}
#^^^^^^-- matching letters and underscore
 

Похоже, что вам нужно записать, однако, не число, как показывает ваше регулярное выражение, а также имя файла в строке, подобной этой: name_of_file210618.A001 . В этом случае вам потребуется выполнить еще несколько операций. Возможно, можно выполнить подстановку для удаления нежелательных символов, но гораздо проще просто использовать регулярное выражение и объединение, как это

 use strict;
use warnings;
use Data::Dumper;

while (<DATA>) {
    my ($name, $num) = /([pL_] )d*(d{6}.Ad{3})/;
    my $str = join '', $name, $num;
    print Dumper $str;
}

__DATA__
name_of_file210618.A001.6476871457
name_of_file0000000546210618.A001.6476871457
foo_of_bar210618.A001.6476871457
 

Это приведет к печати

 $VAR1 = 'name_of_file210618.A001';
$VAR1 = 'name_of_file210618.A001';
$VAR1 = 'foo_of_bar210618.A001';