Как убрать предупреждение «Использование неинициализированного значения»? - PullRequest
1 голос
/ 26 сентября 2008

Допустим, я хочу написать регулярное выражение для изменения всех тегов <abc>, <def> и <ghi> на теги <xyz>, а также я хочу изменить их закрывающие теги на </xyz>. Это выглядит как разумное регулярное выражение (игнорируйте обратные пометки; у StackOverflow есть проблемы со знаками «меньше», если я их не включаю):

`s!<(/)?(abc|def|ghi)>!<${1}xyz>!g;`

И это тоже работает. Единственная проблема заключается в том, что для открытия тегов необязательной переменной $ 1 присваивается значение undef, и поэтому я получаю предупреждение «Использование неинициализированного значения ...».

Какой элегантный способ это исправить? Я бы предпочел не превращать это в два отдельных регулярных выражения, одно для открывающих тегов и другое для закрывающих тегов, потому что тогда нужно сохранить две копии списка тегов вместо одной.

Редактировать: Я знаю, что могу просто отключить предупреждения в этой области кода, но я не считаю это "элегантным".

Ответы [ 9 ]

10 голосов
/ 26 сентября 2008

Переместите вопросительный знак внутри захватной скобки. Таким образом, $ 1 всегда будет определяться, но может быть строкой нулевой длины.

2 голосов
/ 26 сентября 2008

Как насчет:

`s!(</?)(abc|def|ghi)>!${1}xyz>!g;`
1 голос
/ 26 сентября 2008

s!<(/?)(abc|def|ghi)>!<${1}xyz>!g;

Разница только в том, что меняется "(/)?" на "(/?)". Вы уже определили несколько функциональных решений. Я думаю, в этом есть та элегантность, о которой вы просили.

1 голос
/ 26 сентября 2008

Вот один из способов:

   s!<(/?)(abc|def|ghi)>!<$1xyz>!g;

Обновление: удален ненужный комментарий об использовании (?:pattern).

1 голос
/ 26 сентября 2008

Вы можете просто сделать свой первый матч (</?) И избавиться от жестко закодированного <на стороне "замены". Тогда $ 1 всегда будет иметь «<» или «</». Могут быть более элегантные решения для решения проблемы предупреждения, но это должно решить практическую проблему. </p>

0 голосов
/ 27 сентября 2008

Будьте осторожны, поскольку HTML немного сложнее, чем кажется на первый взгляд. Например, вы хотите изменить "" на ""? Ваше регулярное выражение не будет. Хотите изменить "image'>"? Регулярное выражение будет. Вместо этого вы можете захотеть сделать что-то вроде этого:

use HTML::TreeBuilder;
my $tree=HTML::TreeBuilder->new_from_content("<abc>asdf</abc>");
for my $tag (qw<abc def ghi>) {
  for my $elem ($tree->look_down(_tag => $tag)) {
    $elem->tag('xyz');
  }
}
print $tree->as_HTML;

Это избавляет вас от необходимости разбирать HTML-фрагменты самостоятельно.

0 голосов
/ 26 сентября 2008

Я бы предпочел не делать это на две части отдельные регулярные выражения, один для открытия тегов и еще один для закрытия тегов, потому что тогда есть две копии taglist, который необходимо поддерживать

Почему? Поместите ваш taglist в переменную и интерполируйте эту переменную в любое количество регулярных выражений. Я бы подумал об этом даже с одним регулярным выражением, потому что оно гораздо более читаемо с помощью сложного регулярного выражения (а какое регулярное выражение не сложно?).

0 голосов
/ 26 сентября 2008

Чтобы регулярное выражение захватывало $ 1 в любом случае, попробуйте:

  s!<(/|)?(abc|def|ghi)>!<${1}xyz>!g;
       ^
       note the pipe symbol, meaning '/' or ''

Для '' это будет захватывать '' между '<' и 'abc>', а для '' захватывать '/' между '<' и 'abc>'.

0 голосов
/ 26 сентября 2008

Добавить

no warnings 'uninitialized';

или

s!<(/)?(abc|def|ghi)>! join '', '<', ${1}||'', 'xyz>' !ge;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...