Проблема не в том, что специальные символы в ваших строках - как простые строки и регулярные выражения - не спасся, и у вас нет use warnings
в верхней части программы, которая бы предупредил вас об этом.
Например, если добавить use warnings
и использовать Data::Dump
для отображения @links
массива я получаю этот
Unrecognized escape \h passed through at E:\Perl\source\dd.pl line 8.
Unrecognized escape \k passed through at E:\Perl\source\dd.pl line 8.
[
"incl -s projectA /. /abc/cde/efg",
"incl -s projectA . hijklm\nop",
]
Таким образом, некоторые из слеша второго элемента исчезли.
Теперь регулярное выражение выглядит отлично на лице, но я надеюсь, что это ясно, что ваше Чередование распространяется на всю длину образца, так
m{incl -s projectA /. /|\\.\\(.+)}
спички либо
incl -s projectA /./
или
\\.\\(.+)
, что совсем не то, что вы имели в виду. Вам также необходимо избегать точек .
, которые в противном случае соответствуют любому символу, отличному от новой строки; и вы потеряли место, поэтому у вас есть либо /. /
(с интернетом), либо \.\
(без одного).
Это немного сложнее исправить, чем вы могли бы надеяться, потому что (я думаю) вы хотите захватить все после projectA
, но также и для перемотки вперед или назад. Это стало бы
m{incl -s projectA ((?:/\. /|\\\. \\).+)}
, который, используя модификатор /x
и заменяя буквенные пространства с \s+
, я надеюсь, вы согласитесь, может быть более четко написано
m{ incl \s+ -s \s+ projectA \s+ ((?: /\. \s+/| \\\. \s+ \\) .+) }x
Вот исправленная версия кода, который включает в себя все изменения, которые я описал.
use strict;
use warnings;
my @links = (
'incl -s projectA /. /abc/cde/efg',
'incl -s projectA \. \hij\klm\nop',
);
my ($path, $link, @linkpaths, $op);
my $substr = "/";
for my $link (@links) {
$link =~ m{incl \s+ -s \s+ projectA \s+ ((?: /\. \s+/| \\\. \s+ \\) .+)}x;
$path = $1;
print "Path is $path \n";
if (index($path, $substr) >= 0) {
print "$link contains $substr\n";
$op = "/";
}
else {
print "$link doesn't contain $substr\n";
$op = "\\";
}
push @linkpaths, "$path$op";
}
print "\n";
print "linkpaths:\n";
print "$_\n" for @linkpaths;
выход
Path is /. /abc/cde/efg
incl -s projectA /. /abc/cde/efg contains/
Path is \. \hij\klm\nop
incl -s projectA \. \hij\klm\nop doesn't contain/
linkpaths:
/. /abc/cde/efg/
\. \hij\klm\nop\
Update
Чтобы захватить только последний путь в каждом элементе списка ввода, который начинается с косой черты или обратной косой черты, Я бы заменил конец рисунка на этот (?: /\. \s+ | \\\. \s+) (.+)
. Но я считаю, что использовать символ-символ для представления либо прямой, либо обратной косой черты, например, [/\\]
.
Это еще одно изменение в вашей полной программе
use strict;
use warnings;
my @links =(
'incl -s projectA /. /abc/cde/efg',
'incl -s projectA \. \hij\klm\nop',
);
my @linkpaths;
my $substr = '/';
for (@links) {
next unless my ($path) = m{ incl \s+ -s \s+ projectA \s+ [/\\]\. \s+ ([/\\].+) }x;
print "Path is $path\n";
my $op;
if ($path =~ /\Q$substr/) {
printf "%s contains %s\n", $_, $substr;
$op = '/';
}
else {
printf "%s doesn't contain %s\n", $_, $substr;
$op = '\\';
}
push @linkpaths, "$path$op";
}
print "\n";
print "linkpaths:\n";
print "$_\n" for @linkpaths;
выход
Path is /abc/cde/efg
incl -s projectA /. /abc/cde/efg contains/
Path is \hij\klm\nop
incl -s projectA \. \hij\klm\nop doesn't contain/
linkpaths:
/abc/cde/efg/
\hij\klm\nop\
Вы всегда должны проверить на матч, прежде чем использовать переменные захвата 'если ($ ссылка = ~ т { } g) {...} ' – sln