Вы читаете файлы построчно, вам нужно прочитать их либо по абзацу (куски, разделенные пустой строкой), либо весь файл, если такого разделения нет; в противном случае $_
содержит только одну строку и не будет совпадать.
Кроме того, флаг /m
- это не то, что вы ищете (/m
делает ^
/ $
соответствует началу / концу строк), вам нужно /s
, что делает .
включать переводы строки (см. страницу документации perlreref , страница perlop немного сбивает с толку)
По абзацу, этот один вкладыш должен сделать свое дело:
$ perl -l -00 -ne 'if ( /module (\w+)\((.+)\)/s) { @ports = split(/\s*,\s*/,$2); print "Module name: $1 Ports: " . join(", ", @ports)}' <<'EOF'
> module module_name1(in1, in2,
> in3, in4, in5,
> out1, out2, out3,
> out4, out5);
>
>
> module module_name2(in21, in22,
> in23, in24, in25,
> out21, out22, out23,
> out24, out25);
> EOF
Module name: module_name1 Ports: in1, in2, in3, in4, in5, out1, out2, out3, out4, out5
Module name: module_name2 Ports: in21, in22, in23, in24, in25, out21, out22, out23, out24, out25
Вы можете использовать -MO=Deparse
, чтобы увидеть весь код:
perl -MO=Deparse -l -00 -ne 'if ( /module (\w+)\((.+)\)/s) { @ports = split(/\s*,\s*/,$2); print "Module name: $1 Ports: " . join(", ", @ports)}'
BEGIN { $/ = ""; $\ = "\n"; }
LINE: while (defined($_ = <ARGV>)) {
chomp $_;
if (/module (\w+)\((.+)\)/s) {
@ports = split(/\s*,\s*/, $2, 0);
print "Module name: $1 Ports: " . join(', ', @ports);
}
}
Если у вас нет пустых строк, разделяющих модули, вам нужно получить весь файл сразу ( slurp)
perl -l -0777 -ne 'while (/module (\w+)\((.+?)\);/sg) { @ports = split(/\s*,\s*/,$2); print "Module name: $1 Ports: " . join(", ", @ports)}' <<'EOF'
> module module_name1(in1, in2,
> in3, in4, in5,
> out1, out2, out3,
> out4, out5);
> module module_name2(in21, in22,
> in23, in24, in25,
> out21, out22, out23,
> out24, out25);
> EOF
Module name: module_name1 Ports: in1, in2, in3, in4, in5, out1, out2, out3, out4, out5
Module name: module_name2 Ports: in21, in22, in23, in24, in25, out21, out22, out23, out24, out25
Опять же, вы можете использовать -MO=Deparse
, чтобы увидеть, что происходит:
perl -MO=Deparse -l -0777 -ne 'while (/module (\w+)\((.+?)\);/sg) { @ports = split(/\s*,\s*/,$2); print "Module name: $1 Ports: " . join(", ", @ports)}'
BEGIN { $/ = undef; $\ = "\n"; }
LINE: while (defined($_ = <ARGV>)) {
chomp $_;
while (/module (\w+)\((.+?)\);/gs) {
@ports = split(/\s*,\s*/, $2, 0);
print "Module name: $1 Ports: " . join(', ', @ports);
}
}
Ключевым элементом в этих подходах является -0
флаг, который в форме -00
устанавливает $/
в пустую строку, активирующую режим абзаца, а в -0777
форме устанавливает $/
в неопределенное состояние, включающее режим глухоты (чтение всего файла) (см. также: $ RS в руководстве по perlvar.)
Важное предупреждение: -l
устанавливает переменную $\
равной $/
(которая по умолчанию это «\ n»), и в этом случае он должен использоваться перед -0
в командной строке, если вы хотите, чтобы вывод был разделен новыми строками.
Для более элегантного подхода вы можете использовать следующий скрипт:
#!/bin/perl
use warnings;
use strict;
use File::Slurp;
use Data::Dumper;
my $data = read_file($ARGV[0]);
my %modules = $data =~ /module (\w+)\((.+?)\);/sg;
$modules{$_} = [split(/\s*,\s*/, $modules{$_})] for keys(%modules);
print Dumper(\%modules);
Это даст вам структуру данных, содержащую всю необходимую информацию - см. https://ideone.com/BuuR8I для живого демо