В чем разница в Perl при передаче переменной в регулярном выражении между использованием $variable и ${variable}
Вопрос
Я рассматриваю некоторые триггеры ClearCase, написанные на Perl.Я заметил, что в некоторых регулярных выражениях переменные передаются либо прямолинейно, либо с их именами в фигурных скобках.
Например, у меня есть следующая строка кода в триггере:
if ($baseline !~ /^${component}_(|.*_)$phase\.\d+(|[a-z]|-\d+|${automateddigit})$/ &&
$baseline !~ /^${project_root}_$phase\.\d+(|[a-z]|-\d+|${automateddigit})$/)
$component
, $phase
, $automateddigit
, $project_root
это все переменные.
Почему некоторые передаются как $variable
а другие передавались как ${variable}
в регулярном выражении?
Зависит ли это от того, как они инициализируются?
Вот строка кода, инициализирующая их:
($project = $ENV{CLEARCASE_PROJECT}) =~ s/\@.*$//;
($component = $ENV{CLEARCASE_COMPONENT}) =~ s/\@.*$//;
($project_root, $phase) = ($project =~ /^(.*)_(R\d+.*)$/);
exit(0) if (! $phase);
$phase .= ".0" if ($phase =~ /^R\d+$/);
$automateddigit = '';
$istream = `cleartool desc -fmt "%[istream]p" project:$ENV{CLEARCASE_PROJECT}`;
$componentlist = `cleartool desc -fmt "%[components]Cp" stream:$ENV{CLEARCASE_STREAM}`;
$componentsnbr = split(',', $componentlist);
if ($componentsnbr > 1) {
$automateddigit .= '\\.\\d+';
}
Решение
Если вы передаете переменную как ${name}, это явно определяет, где находится конец имени переменной и где начинается остальная часть строки, заключенной в кавычки.Например, в вашем коде:
if ($baseline !~ /^${component}_(|.*_)$phase\.\d+(|[a-z]|-\d+|${automateddigit})$/ &&
Без {}
разделители:
if ($baseline !~ /^$component_(|.*_)$phase\.\d+(|[a-z]|-\d+|${automateddigit})$/ &&
Обратите внимание, что переменная $component (вы можете ссылаться на нее любым способом) будет неверно истолкована как $component_ из-за завершающего подчеркивания в регулярном выражении.
Другие советы
Во-первых, это называется интерполяцией строк.Одна из веских причин использовать его в этом случае - предотвратить интерпретацию $project_root как $project_root_ (обратите внимание на завершающий символ подчеркивания).Это делает явным имя переменной, вместо того чтобы оставлять его на усмотрение более сложных правил интерполяции.
Смотрите perldata для получения дополнительной информации об интерполяции, а perlre и perlop - об особенностях интерполяции в операторах регулярных выражений.
Как упоминалось выше, он предназначен для разграничения имен переменных.Слишком много фигурных скобок делают и без того сложные регулярные выражения еще сложнее.Фигурные скобки имеют свое собственное регулярное выражение (для ограничения количества совпадений с шаблоном).Я бы рекомендовал использовать модификатор regexp / x и переписать ваше регулярное выражение следующим образом:
if ($baseline !~ /^$component # Start with $component
_ # then an underscore
(|.*_) # Then nothing, or anything followed by an underscore
$phase # ...
\.\d+ # ...
(| # Then optionally:
[a-z]| # lower alpha
-\d+| # or ...
$automateddigit
)
$/x &&
$baseline !~ /^$project_root
_
$phase
\.\d+
(|
[a-z]|
-\d+|
$automateddigit
)$/x)