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、入力に 4 桁以上の 16 進数があるとオーバーフローします。64 ビットの整数を持つ Perl は、12 桁の 16 進数を処理します。


ここからコードを取得したようです。入力として MAC アドレスを受け取ることを意図しています。つまり、コードが機能するには 64 ビット整数またはMath::BigIntが必要です。64ビット値をモジュラスにしたいので、それを回避する方法はありません。


64 ビット整数の Perl でのみ動作する簡潔な方法を次に示します。

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

プログラムの最初の引数として連結された 16 進数のオクテットの束を探し、モジュラスを適用します。

したがって、プログラムが次のように呼び出された場合:

$ myprog.pl A0B0

の値は に$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:単一行;

つまり、最初の16進数を取り除き、次にバイトの順序を逆にして(一度に2つの16進数)、結果に対してモジュロを実行します。

于 2012-07-13T15:14:04.260 に答える