3

我需要获得在这一点 Perl 代码中使用的算法,但我对 Perl 一无所知。通常这不是问题,因为我会研究语言,但是这个正则表达式的东西让我头疼!

有人可以对此进行伪代码吗?我只需要知道发生了什么,这样我就可以用其他东西来实现它,最好是 PHP 甚至 C++,但我会担心那部分。我只需要以某种方式破译这是在做什么:

$a = $ARGV[0];
$a =~ s/[^A-F0-9]+//simg;
@b = reverse split /(\S{2})/,$a;
$c = join "", @b;
$c .= "0000";
$d = hex($c) % 999999929;
print "$d\n";
4

4 回答 4

10

有什么不好写的?它可以使用更好的 var 名称,但我不知道这是否可能(因为中间步骤似乎没有任何可命名的质量),只留下split. 伪代码几乎是一个字一个字的翻译。

$a = $ARGV[0];
$a =~ s/[^A-F0-9]+//simg;
@b = reverse split /(\S{2})/,$a;
$c = join "", @b;
$c .= "0000";
$d = hex($c) % 999999929;
print "$d\n";

应该

$a = $ARGV[0];                # Get a hex str from cmd line   E3:C9:D4
$a =~ s/[^A-F0-9]+//simg;     # Remove any non-hex digits     E3C9D4
@b = reverse $a =~ /(..)/sg;  # Extract "bytes"; reverse      D4, C9, E3
$c = join "", @b;             # Join them.                    D4C9E3
$c .= "0000";                 # Append two NULs               D4C9E30000
$d = hex($c) % 999999929;     # Convert from hex to number and modulus
print "$d\n";                 # Print the result (in decimal).

稍微清楚一点:

$a = $ARGV[0];
$a =~ s/[^0-9A-Fa-f]+//g;
$a = join '', reverse $a =~ /(..)/sg;
$a .= "0000";
$a = hex($a);
$a %= 999999929;
print "$a\n";

这些片段中可能存在错误。在具有 32 位整数的 Perl 上,hex如果输入的十六进制数字超过四个,则会溢出。具有 64 位整数的 Perl 将处理 12 个十六进制数字。


您似乎已从此处获取代码。这意味着将 MAC 地址作为输入,这意味着代码需要 64 位整数或Math::BigInt才能工作。没有办法解决它,因为您想对 64 位值取模。


这是一种只适用于 64 位整数的 Perls 的简洁方法:

my $mac = $ARGV[0];
$mac =~ s/[^0-9A-Fa-f]+//g;
die length($mac) != 12;

# "123456789ABC" => 0xBC9A785634120000
my $hash = unpack('Q<', pack('H*', "0000$mac"));

$hash %= 999999929;
print "$hash\n";

为了可移植性,最好将 Math::BigInt 集成到早期版本中。

于 2012-07-13T15:26:44.827 回答
2

它正在寻找一组连接在一起的十六进制八位字节作为程序的第一个参数,并应用模数。

因此,如果程序被调用为:

$ myprog.pl A0B0

那么 in 的值$c将是B0A00000。因此, 的值$d应该是0x396A6C8E

这是由害怕packunpack的人编写的一段特别糟糕的代码。

于 2012-07-13T15:07:30.423 回答
2
$a = $ARGV[0]; # assign first command line arg to $a
$a =~ s/[^A-F0-9]+//simg; # delete non-hex from $a
@b = reverse split /(\S{2})/,$a; # split $a by 2 non-whitespace (saving them too) to array  @b and reverse it
$c = join "", @b; # join array @b to scalar $c
$c .= "0000"; # append 4 zeros to $c
$d = hex($c) % 999999929; # get modulo
print "$d\n"; # print it
于 2012-07-13T15:07:31.093 回答
1
$a = $ARGV[0]; #Read in the first argument on the command line
$a =~ s/[^A-F0-9]+//simg; #Substitute non hex numbers with nothing *
@b = reverse split /(\S{2})/,$a; #What is left in $a, split by 2 non-space characters
$c = join "", @b; # put the array b into $c
$c .= "0000"; 
$d = hex($c) % 999999929; #Convert $c to an integer and % with 999999929
print "$d\n";
  • simg = i:不区分大小写;g:全球;m:多行;s:单行;

简而言之,我们剥离第一个十六进制数,然后颠倒字节顺序(一次 2 个十六进制数)并对结果进行取模。

于 2012-07-13T15:14:04.260 回答