如何将字符串化版本的数组引用转换为Perl中的实际数组引用?

Tim*_*Tim 10 perl

有没有办法让Perl将数组引用的字符串化版本(例如ARRAY(0x8152c28))转换为实际的数组引用?

例如

perl -e 'use Data::Dumper; $a = [1,2,3];$b = $a; $a = $a.""; warn Dumper (Then some magic happens);'
Run Code Online (Sandbox Code Playgroud)

会屈服

$VAR1 = [
      1,
      2,
      3
    ];
Run Code Online (Sandbox Code Playgroud)

yst*_*sth 17

是的,你可以这样做(即使没有内联C).一个例子:

use strict;
use warnings;

# make a stringified reference
my $array_ref = [ qw/foo bar baz/ ];
my $stringified_ref = "$array_ref";

use B; # core module providing introspection facilities
# extract the hex address
my ($addr) = $stringified_ref =~ /.*(0x\w+)/;
# fake up a B object of the correct class for this type of reference
# and convert it back to a real reference
my $real_ref = bless(\(0+hex $addr), "B::AV")->object_2svref;

print join(",", @$real_ref), "\n";
Run Code Online (Sandbox Code Playgroud)

但不要这样做.如果您的实际对象被释放或重用,您最终可能会得到段错误.

无论你实际想要实现什么,肯定有更好的方法.对另一个答案的评论表明,字符串化是由于使用引用作为哈希键.作为回应,更好的方法是经过良好战斗测试的 Tie :: RefHash.


Sco*_*ttJ 6

第一个问题是:你真的想这样做吗?

这个字符串来自哪里?

如果它来自你的Perl程序之外,指针值(十六进制数字)将毫无意义,并且没有办法做到这一点.

如果它来自您的程序内部,那么首先不需要对其进行字符串化.

  • 如果要将ref用作散列键,请使用Tie :: RefHash.字符串化是不安全的.也不是"refaddr $ ref".如果您不知道为什么,请坚持使用Tie :: RefHash.角落箱在那里妥善处理. (5认同)
  • @Tim:假设你真的想要这样做,"如果它来自你的程序内部,那么首先就没有必要对它进行字符串化." (2认同)

tob*_*ink 5

是的,有可能:使用Devel :: FindRef

use strict;
use warnings;
use Data::Dumper;
use Devel::FindRef;

sub ref_again {
   my $str = @_ ? shift : $_;
   my ($addr) = map hex, ($str =~ /\((.+?)\)/);
   Devel::FindRef::ptr2ref $addr;
}

my $ref = [1, 2, 3];
my $str = "$ref";
my $ref_again = ref_again($str);

print Dumper($ref_again);
Run Code Online (Sandbox Code Playgroud)