2012-06-01 7 views
20

私はlast.fmが私の地域で雇用していることに気がつきました。私はいくつかの人を知っていたので、who workedthereと申します。このPerlの1ライナーは実際にどのように動作しますか?

しかし、最初にcurrent staffを調べてみるのがよいと思いました。

このページの誰もが、「人生は自分自身を退屈させるにはあまりにも短いものではありませんか?」のようなかわいい/巧妙な/ばかなストラップラインを持っています。

:私は私の端子(多分、行うには愚かなものの一種)に貼り付けるに抵抗することができませんでしたが、それは印刷

perl -e'print+pack+q,c*,,map$.+=$_,74,43,-2,1,-84, 65,13,1,5,-12,-3, 13,-82,44,21, 18,1,-70,56, 7,-77,72,-7,2, 8,-6,13,-70,-34' 

:私はこれに着くまで、実際には、それは、かなり面白かったです

ちょうど別のLast.fmのハッカー、

私はPerlのワンライナーがどのように機能するかを理解することは比較的容易だろうと思いました。しかし、私は実際にドキュメントを理解することができませんでした。私はPerlを知らないので、関連するドキュメントを読んでいるかどうかもわかりませんでした。

私は数字を変更しようとしましたが、私はどこにもいませんでした。だから私はそれが本当に面白いと思う価値があると決めました。

だから、「どのように動作しない」ビット漠然としている、私の質問は主に、

は、これらの数字は何ですか?なぜ負の数と正の数があり、負の意味か陽性の問題か?

オペレータ+=$_の組み合わせは何ですか?

pack+q,c*,,は何をしていますか?

+0

私の現在のもの: '(* STORE、* TIESCALAR)= map {eval" sub {$ _} "} qw'map {print && sleep $ |} split //、pop bless \ $ | ++ '; tie $ t、main; $ t = "ちょうど別のPerlハッカー、\ n" ' –

答えて

28

これは“Just another Perl hacker”のバリアント、Perlのミームです。 JAPHが行っているように、これは比較的飼い慣らされています。

最初にする必要があることは、perlプログラムを解析する方法を理解することです。それは関数呼び出しの周りにかっこがなく、興味深い方法で+と引用符のような演算子を使用します。元のプログラムはこれです:

print+pack+q,c*,,map$.+=$_,74,43,-2,1,-84, 65,13,1,5,-12,-3, 13,-82,44,21, 18,1,-70,56, 7,-77,72,-7,2, 8,-6,13,-70,-34 

packprintmaplist operatorsであるのに対し、関数です。いずれにしても、ファンクションまたはヌル以外の演算子名の直後にプラス記号が続く場合は、+をバイナリ演算子として使用できないため、先頭の+符号は両方ともunary operatorsです。この奇妙なことは、manualに記載されています。

我々は括弧を追加する場合は、map用ブロックの構文を使用して、空白のビットを追加し、我々が得る:

print(+pack(+q,c*,, 
      map{$.+=$_} (74,43,-2,1,-84, 65,13,1,5,-12,-3, 13,-82,44,21, 
         18,1,-70,56, 7,-77,72,-7,2, 8,-6,13,-70,-34))) 

次のトリッキーなビットは、ここqqquote-like operatorであるということです。これは、より一般的に単一引用符で書かれています:物事が今より身近見ている必要がありますので

print(+pack(+'c*', 
      map{$.+=$_} (74,43,-2,1,-84, 65,13,1,5,-12,-3, 13,-82,44,21, 
         18,1,-70,56, 7,-77,72,-7,2, 8,-6,13,-70,-34))) 

は、単項プラスは(離れてスカラーコンテキストを強制するから)何もしませんことを覚えておいてください。これはという形式のpack関数への呼び出しであり、「現在の文字セット内の数字で指定された任意の数の文字」を意味します。これを書くための代替方法は、map機能が順序で引数リストの要素に供給されるブロックを適用

print(join("", map {chr($.+=$_)} (74, …, -34))) 

あります。各要素について、$_は要素値に設定され、map呼び出しの結果は、連続する要素に対してブロックを実行することによって返される値のリストです。このプログラムを書くための長い道は

@list_accumulator =(); 
for $n in (74, …, -34) { 
    $. += $n; 
    push @list_accumulator, chr($.) 
} 
print(join("", @list_accumulator)) 

$.変数が数字の累計を含んでいるだろう。数値は、実行中の合計が、著者が印刷したい文字のASCIIコードであるように選択されます。74 = J,74 + 43 = 117 = u,74 + 43-2 = 115 = sなどです。各文字がASCII順で前の文字か後の文字かに応じて正の値をとります。

次の作業については、このJAPH(EyesDropで作成)を説明してください。

''=~('(?{'.('-)@.)@_*([]@[email protected]/)(@)@[email protected]),@(@@[email protected])' 
^'][)@]`}`]()`@[email protected]]@%[`}%[@`@!#@%[').',"})') 

プロダクションコードでは使用しないでください。

+1

この回答はすべて素晴らしいです。大きな説明、リンクを追加した、フォローアップを追加した –

22

これの背後にある基本的な考え方は非常に簡単です。文字のASCII値を含む配列があります。物事を少し複雑にするために、絶対値は使用せず、最初のものを除いて相対値を使用します。そう考えは、例えば、一つ前に特定の値を追加することである。

  1. 74 - >J
  2. 74 + 43 - >u
  3. 74 + 42 +(-2) - >s

$.がPerlの特別な変数であっても、この場合は特別な意味を持ちません。

map($.+=$_, ARRAY) 

は、基本的には変数$.に現在のリスト要素($_)を追加すること:ちょうど前の値を保存し、現在の要素を追加するために使用されます。これにより、新しい文の正しいASCII値を持つ新しい配列が返されます。

Perlのq関数は、シングルクォートのリテラル文字列に使用されます。例えば。あなたはこれがpack+q,c*,,は基本的にpack 'c*', ARRAYであることを意味し

q/Literal $1 String/ 
q!Another literal String! 
q,Third literal string, 

のようなものを使用することができます。c*修飾子をpackに設定すると、その値が文字として解釈されます。たとえば、値を使用して文字として解釈します。

それは基本的にこれに沸く:

#!/usr/bin/perl 
use strict; 
use warnings; 

my $prev_value = 0; 

my @relative = (74,43,-2,1,-84, 65,13,1,5,-12,-3, 13,-82,44,21, 18,1,-70,56, 7,-77,72,-7,2, 8,-6,13,-70,-34); 
my @absolute = map($prev_value += $_, @relative); 

print pack("c*", @absolute); 
関連する問題