我有一个 Perl 脚本,它从长度超过 X 个字符的 C 源文件中构建符号的哈希值,然后替换字符串
A[0-9]{5}
。数字随着每个连续符号的缩短而增加。这是为了准备在非常旧的编译器上编译的代码,对符号的长度有奇怪的限制。
在将 sed 脚本拉入 Perl 程序中,我能够将旧的外部 sed 脚本方法转换为直接在 Perl 中工作(大部分)。现在的问题是我收到了投诉
Use of uninitialized value within %transformations in substitution iterator at src/misc/snavig.pl line 210, <> line 8.
约1600次。问题出在这段代码中,它应用了替换:
my $oldsymbols = join '|', keys %transformations;
my $oldfilenames = join '|', keys %includes;
local $^I = '.bak';
local @ARGV = glob("*.c *.h");
while (<>) {
s/\b($oldsymbols)\b/$transformations{$1}/g;
s/($oldfilenames)/$includes{$1}/g;
print;
}
%transformations
哈希看起来像这样:
hide_lines => 'A00058'
message => 'A00165'
tokenise_text => 'A00388'
z_print_addr => 'A00220'
z_ret_popped => 'A00236'
encode_text => 'A00384'
我已经追踪到整行替换匹配的第一部分,并将其放入
$1
中。所以当然 compression_names[compression_mode], hide_lines);
不会作为该哈希中的键出现。我不明白的是如何保护 $oldfilenames
字符串,以便 $1
只会接收该字符串中的符号之一。 %includes
中的替换不会引起投诉,因为整行总是匹配一个键。
我不记得我在哪里找到了用
\K ... (?=.)
或 \K ... (?=.*)
在 \b
事物内外保护它的建议。这些要么什么也没做,要么弄得一团糟。消除这些抱怨的正确有效方法是什么?
编辑以添加示例数据:
加工前:
/*
* print_char
*
* High level output function.
*
*/
void print_char(zchar c)
{
static bool flag = FALSE;
need_newline_at_exit = TRUE;
if (message || ostream_memory || enable_buffering) {
if (!flag) {
/* Characters 0 and ZC_RETURN are special cases */
if (c == ZC_RETURN) {
new_line();
return;
}
加工后:
/*
* A00267
*
* High level output function.
*
*/
void A00267(zchar c)
{
static bool flag = FALSE;
A00174 = TRUE;
if (A00165 || A00162 || A00173) {
if (!flag) {
/* Characters 0 and ZC_RETURN are special cases */
if (c == ZC_RETURN) {
A00266();
return;
}
在注释掉的区域内进行替换是可以的。
我已经追踪到整行替换匹配的第一部分,并将其放入 $1 中。
您的正则表达式不匹配完整的行,除非您的真实代码中有某些内容您尚未向我们展示。
运行此程序时我没有发现问题
my %transformations = (
hide_lines => 'A00058',
message => 'A00165',
tokenise_text => 'A00388',
z_print_addr => 'A00220',
z_ret_popped => 'A00236',
encode_text => 'A00384',
);
my $oldsymbols = join '|', keys %transformations;
while (<DATA>) {
s/\b($oldsymbols)\b/$transformations{$1}/g;
print;
}
__END__
hide_lines
message
tokenise_text
compression_names[compression_mode], hide_lines);
它做了正确的事
$ perl try.pl
A00058
A00165
A00388
compression_names[compression_mode], A00058);
您可以更新问题吗?
您的帖子中缺少信息,或者某些信息不正确。 (如果这不能回答您的问题,您需要提供问题的实际演示。)
我猜问题是你的钥匙里有特殊符号。例如,考虑一下您有一个名为
foo*
的键的情况。这将匹配 foo
(以及其他),它可能不在您的哈希中。
您可以通过添加以下内容来验证这是否是问题所在:
if ( my @errors = sort grep /\W/, keys %transformations ) {
die(
join "",
map "Transformation key `$_` contains non-word symbols\n",
@errors
);
}
如果是故意的,您可以更换
my $oldsymbols = join '|', keys %transformations;
与
my $oldsymbols = join '|', map quotemeta, keys %transformations;
但请注意,如果某个键以非单词字符开头或结尾,则锚定
\b
将不会按预期运行。