perl 打包和解包是相反的吗?

lokaqttq  于 2023-03-30  发布在  Perl
关注(0)|答案(3)|浏览(140)

这个问题是超级用户的migrated,因为昨天可以在Stack Overflow.Migrated上回答。
我一直认为Perl中的packunpack在某种意义上是相反的。但是,第二个命令什么也不打印。为什么?

$ perl -le 'print unpack("N", 127.0.0.1)'

2130706433

$ perl -le 'print pack("N", 2130706433)'

nothing is here
8dtrkrch

8dtrkrch1#

不,它打印了四个字节-没有一个碰巧是“可见的”ASCII字符,但它们正好对应于127.0.0.1的原始值:

$ perl -le 'print pack("N", 2130706433)' | hexdump -C
00000000  7f 00 00 01 0a                                    |.....|
00000005

如果您尝试不使用pack/unpack打印此值,您将获得完全相同的结果:

$ perl -le '$a = 127.0.0.1; print $a' | hexdump -C
00000000  7f 00 00 01 0a                                    |.....|
00000005

这里的问题是127.0.0.1"127.0.0.1"不是一回事,它是一个Perl特定的“版本字符串”文字,* 已经 * 存储为压缩字节串,相当于"\x7f\x00\x00\x01"

zu0ti5jz

zu0ti5jz2#

是的,它们是彼此的逆。

  • pack "N"将值编码为32位的大端无符号整数。
  • unpack "N"将32位大字节无符号整数解码为值。

对于有效输入,以下情况为真:

  • unpack( "N", pack( "N", $x ) ) == $x
  • pack( "N", unpack( "N", $x ) ) eq $x

127.0.0.1v127.0.0.1的缩写。它们被称为版本字符串或“v”字符串。以下是等效的:

  • 127.0.0.1
  • v127.0.0.1
  • pack "C*", split /\./, "127.0.0.1"
  • chr( 127 ) . chr( 0 ) . chr( 0 ) . chr( 1 )
  • "\x7F\x00\x00\x01"

所有这些都产生一个四字节的字符串,由值127、0、0和1组成。
值得注意的是,127.0.0.1 * 不 * 等价于"127.0.0.1"。您希望inet_ntoainet_ntop获得字符串127.0.0.1,而不是unpack "N"
生成的字符串中没有一个字符是可打印的,这就是为什么在打印它们时得到“nothing”的原因。我将使用od来更好地了解打印的内容。

$ perl -e'print 127.0.0.1' | od -t x1
0000000 7f 00 00 01
0000004

$ perl -le'print unpack( "N", 127.0.0.1 )'
2130706433

$ perl -e'print pack( "N", 2130706433 )' | od -t x1
0000000 7f 00 00 01
0000004

正如您所看到的,unpack确实像预期的那样反转了pack

f87krz0w

f87krz0w3#

正如@user1686已经说过的,您将得到一个“机器”编号--一个表示该编号的位模式。
要处理IP号码,您可以使用Socketinet_aton(ASCII到数字)或inet_ntoa(相反):

% perl -MSocket=inet_aton -le 'print unpack q(N), inet_aton(shift)' 127.0.0.1

% perl -MSocket=inet_ntoa -le 'print inet_ntoa(pack q(N), shift)' 2130706433

请注意,在Perl中,文字代码127.0.0.1是历史的一个奇怪的怪癖。这是一种语义版本控制风格“数字”。它会自动打包自己,这就是为什么你的unpack可以工作。如果你有一个文字版本号,这没有什么错,但它不会对字符串起作用。

% perl -le 'print 127.1.0.0' | hexdump -C
00000000  7f 01 00 00 0a                                    |....|
00000004

% perl -le 'print pack q(C*), 127,1,0,0' | hexdump -C
00000000  7f 01 00 00 0a                                    |.....|
00000005

相关问题