消除大组替换中重复的“在模式匹配中使用单位化值 $foo”错误

问题描述 投票:0回答:2

我有一个 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;
                        }

在注释掉的区域内进行替换是可以的。

regex perl hashtable substitution
2个回答
0
投票

我已经追踪到整行替换匹配的第一部分,并将其放入 $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);

您可以更新问题吗?


0
投票

您的帖子中缺少信息,或者某些信息不正确。 (如果这不能回答您的问题,您需要提供问题的实际演示。)

我猜问题是你的钥匙里有特殊符号。例如,考虑一下您有一个名为

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
将不会按预期运行。

© www.soinside.com 2019 - 2024. All rights reserved.