Трудно сказать с информацией, которую вы дали, но я думаю, что проблема в том, что регулярное выражение
$vm =~ m/^(\bguestOSAltName\b)/x;
не соответствует файлу, который вы дали, потому что утверждение ^
соответствует началу строка , а не началу строка .Поскольку регулярное выражение не совпадает, $1
сохраняет свое старое значение ранее в программе, которая выводится на печать.В целях безопасности вы должны проверить регулярное выражение, которое фактически соответствует, перед использованием захватов:
if ($vm =~ m/^(\bguestOSAltName\b)/x) {
print "$1\n";
}
else {
carp "Couldn't find guestOSAltName!";
}
Или захватить захваты, поместив совпадение в контекст списка:
# $result gets $1 if the match succeeds, undef if it fails.
my ($result) = $vm =~ m/^(\bguestOSAltName\b)/x
Чтобы сопоставить ^
для начала, вам нужен модификатор /m
, который меняет ^$
, чтобы соответствовать строке вместо строчной:
if ($vm =~ m/^(\bguestOSAltName\b)/xm) { ... }
Вот почему Дамиан Конвей в Perl Best Practices рекомендует вам всегда используйте /m
- потому что тогда ^$
всегда делают то, что вы интуитивно думаете, что они должны делать.[На самом деле он рекомендует всегда использовать /xms
.Вы проходите треть пути :)]
PS: С этого момента все является общей критикой рецензирования кода, не связанной напрямую с вопросом.Я надеюсь, что это полезно, но не стесняйтесь игнорировать это.
Я считаю, что чрезмерное использование экранированных символов в регулярных выражениях и других контекстах с двойными квотами
$vm =~ s/\[/\//;
часто лучше переписать вquotish context:
$vm =~ s'['/';
Кроме того, это регулярное выражение довольно трудно читать:
$vm =~ m/^(\d+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\D+)(\D)(\d)(\d)/x;
Вы используете тег /x
, почему бы не воспользоваться им?
$vm =~ m/^(\d+) \s+ # $1: number of some sort
(\S+) \s+ # $2: identifier we're interested in
(\S+) \s+ # $3: VMX filename part a
(\S+) \s+ # $4: VMX filename part b
(\S+) \s+ # $5: another identifier
(\D+)(\D) # $6, $7: at least two nondigits
(\d) # $8: digit
(\d) # $9: version digit
/x;
Я бы также рассмотрел использование именованных захватов:
$vm =~ m/^(?: \d+) \s+ # number of some sort
(?<ID> \S+) \s+ # $+{ID}: identifier we're interested in
(?<VMXa> \S+) \s+ # $+{VMXa}: VMX filename part a
(?<VMXb> \S+) \s+ # $+{VMXb}: VMX filename part b
(?: \S+) \s+
(?:\D+)(?:\D) # at least two nondigits
(?:\d) # one digit
(?<VERSION> \d) # $+{VERSION}: version digit
/x;
Теперь вместо загадочных ссылок на $2
и $9
впоследствии у вас есть четкие, очевидные, самодокументированные ссылкидо $+{ID}
и $+{VERSION}
.Я превратил остальные группы в группы без захвата (?:regex)
, но если я захочу захватить одну из них позже, я могу превратить ее в именованный захват без изменения индексов всех других захватов, в отличие от позиционныхcapturing.
Именованные захваты также реже страдают от проблемы со старым значением, упомянутой выше, когда неудачный захват оставляет все переменные $1
в их старом состоянии.