perl 摆脱大替换集合中重复出现的“在模式匹配中使用单位化值$foo”错误

sgtfey8w  于 2023-08-06  发布在  Perl
关注(0)|答案(2)|浏览(107)

我有一个Perl脚本,它从C源文件中构建一个长度超过X个字符的符号散列,然后替换为A[0-9]{5}字符串。该数字随着每个要缩短的连续符号而递增。这是为了准备要在非常旧的编译器上编译的代码,这些编译器对符号的长度有奇怪的限制。
Pulling a sed script into a perl program中,我能够将旧的外部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;
                        }


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

vbkedwbf

vbkedwbf1#

您的帖子中缺少信息,或者某些信息不正确。(如果这不能回答您的问题,您需要提供问题的实际演示。
我猜问题是你的钥匙上有特殊符号。例如,假设您有一个名为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的行为将不符合预期。

0wi1tuuw

0wi1tuuw2#

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


你能更新一下问题吗?

相关问题