web-dev-qa-db-ja.com

Perlの隠された機能?

あなたが実際に有用な仕事をするために採用することができたPerlのいくつかの本当に便利で難解な言語機能は何ですか?

ガイドライン:

  • CPANではなくPerlコアへの回答を制限してください
  • 例と簡単な説明を教えてください

他の言語の隠し機能にもある隠し機能:

(これらはすべて Corionの答え からのものです)

  • [〜#〜] c [〜#〜]
    • ダフのデバイス
    • 移植性と標準性
  • C#
    • 空白で区切られたリストと文字列の引用符
    • エイリアス可能な名前空間
  • Java
    • 静的イニシャライザー
  • JavaScript
    • 機能はファーストクラス市民です
    • ブロック範囲と閉鎖
    • 変数を介して間接的にメソッドとアクセサーを呼び出す
  • ルビー
    • コードによるメソッドの定義
  • [〜#〜] php [〜#〜]
    • 広範なオンラインドキュメント
    • 魔法の方法
    • シンボリック参照
  • Python
    • 1行の値の交換
    • コア機能も独自の機能に置き換える機能

その他の隠された機能:

演算子:

引用構造:

構文と名前:

モジュール、プラグマ、およびコマンドラインオプション:

変数:

ループとフロー制御:

正規表現:

その他の機能:

その他のトリック、およびメタアンサー:


関連項目:

143
Adam Bellaire

フリップフロップ演算子は、フラグ変数を使用せずに、ファイルハンドルによって返されるレコード(通常は行)をループするときに、最初の反復をスキップするのに役立ちます。

while(<$fh>)
{
  next if 1..1; # skip first record
  ...
}

実行perldoc perlopおよび詳細と例については、「フリップフロップ」を検索してください。

54
John Siracusa

Perlには多くの非自明な機能があります。

たとえば、シギルの後にスペースができることを知っていましたか?

 $ Perl -wle 'my $x = 3; print $ x'
 3

または、シンボリック参照を使用する場合、subsに数値名を付けることができますか?

$ Perl -lwe '*4 = sub { print "yes" }; 4->()' 
yes

「ブール」準演算子もあります。これは、真の式に対して1を返し、偽に対して空の文字列を返します。

$ Perl -wle 'print !!4'
1
$ Perl -wle 'print !!"0 but true"'
1
$ Perl -wle 'print !!0'
(empty line)

他の興味深いもの:use overload文字列リテラルと数字をオーバーロードすることができます(たとえば、BigIntsなどにできます)。

これらの多くは実際にどこかで文書化されているか、文書化された機能に論理的に準拠していますが、それでもあまり知られていないものもあります。

更新:もう1ついいね。 q{...}引用構造が言及されましたが、区切り文字として文字を使用できることをご存知ですか?

$ Perl -Mstrict  -wle 'print q bJet another Perl hacker.b'
Jet another Perl hacker.

同様に、正規表現を書くことができます:

m xabcx
# same as m/abc/
47
moritz

magic ARGVで圧縮ファイルのサポートを追加します。

s{ 
    ^            # make sure to get whole filename
    ( 
      [^'] +     # at least one non-quote
      \.         # extension dot
      (?:        # now either suffix
          gz
        | Z 
       )
    )
    \z           # through the end
}{gzcat '$1' |}xs for @ARGV;

(シェルメタ文字を含むファイル名を処理するために必要な$ _を囲む引用符)

<>機能は@ARGVファイルの末尾が「.gz」または「.Z」の場合:

while (<>) {
    print;
}
46
timkay

Perlで私のお気に入りの機能の1つは、ブール||演算子を使用して、選択肢のセットから選択することです。

 $x = $a || $b;

 # $x = $a, if $a is true.
 # $x = $b, otherwise

つまり、次のように記述できます。

 $x = $a || $b || $c || 0;

$a$b、および$cから最初の真の値を取得するか、そうでない場合はデフォルトの0を取得します。

Perl 5.10には、//演算子もあり、定義されている場合は左側を返し、定義されていない場合は右側を返します。以下は、最初のdefined値を$a$b$c、または0から選択します。

 $ x = $ a // $ b // $ c // 0; 

これらは、省略形を使用することもでき、デフォルトを提供するのに非常に便利です。

 $ x || = 0; #$ xが偽だった場合、値は0になります。
 
 $ x // = 0; #$ xが未定義の場合、値はゼロになります。

チェリオ、

ポール

40
pjf

演算子++および単項-数値だけでなく、文字列でも機能します。

my $_ = "a"
print -$_

-aを出力します

print ++$_

bを出力します

$_ = 'z'
print ++$_

aaを出力します

39
Leon Timmermans

Perlには他のリストからのほとんどすべての「難解な」部分があるので、Perlができない1つのことを説明します。

Perlができないことの1つは、正規表現に//演算子が使用されるため、コードに裸の任意のURLを含めることです。

Perlが提供する機能が明らかでない場合に備えて、完全に明らかではないかもしれないエントリの選択リストを以下に示します。

Duffのデバイス - Perlの場合

移植性と標準性 - CコンパイラよりもPerlを搭載したコンピュータのほうが多いと思われます

ファイル/パス操作クラス - File :: Findは、.Netよりも多くのオペレーティングシステムで動作します

空白で区切られたリストの引用符および文字列 - Perlではリストと文字列の区切り文字にほぼ任意の引用符を選択できます

エイリアス可能な名前空間 -Perlにはこれらのグロブ割り当てがあります:

*My::Namespace:: = \%Your::Namespace

静的イニシャライザ -Perlは、コンパイルとオブジェクトのインスタンス化のほぼすべての段階で、BEGIN(コード解析)からCHECK(コード解析後)からimport(モジュールのインポート時)からnew(オブジェクトのインスタンス化)からDESTROY(オブジェクトの破壊)からEND(プログラム終了)

関数はファーストクラスの市民です -Perlのように

ブロックスコープとクロージャ -Perlには両方があります

変数を介してメソッドとアクセサを間接的に呼び出す -Perlもそれを行います:

my $method = 'foo';
my $obj = My::Class->new();
$obj->$method( 'baz' ); # calls $obj->foo( 'baz' )

コードによるメソッドの定義 - Perlでも許可

*foo = sub { print "Hello world" };

Pervasiveのオンラインドキュメント - Perlのドキュメントはオンラインであり、おそらくシステムにもあります

マジックメソッド 「存在しない」関数を呼び出すたびに呼び出されます-PerlはAUTOLOAD関数でそれを実装します

シンボリックリファレンス -これらから離れることをお勧めします。 彼らはあなたの子供を食べます。 しかし、もちろん、Perlはあなたの子供を血に飢えた悪魔に提供することを許可します。

1行の値の交換 -Perlはリストの割り当てを許可します

コア機能も独自の機能に置き換える機能

use subs 'unlink'; 
sub unlink { print 'No.' }

または

BEGIN{
    *CORE::GLOBAL::unlink = sub {print 'no'}
};

unlink($_) for @ARGV
36
Corion

Autovivification 。知る限り他の言語にはありません

35
J.J.

Perlでは、ほとんどあらゆる種類の奇妙な文字列を引用するのは簡単です。

my $url = q{http://my.url.com/any/arbitrary/path/in/the/url.html};

実際、Perlのさまざまな引用メカニズムは非常に興味深いものです。 Perlの正規表現に似た引用メカニズムにより、区切り文字を指定して、何でも引用できます。 #、/、または()、[]、{}などのオープン/クローズ文字など、ほとんどすべての特殊文字を使用できます。例:

my $var  = q#some string where the pound is the final escape.#;
my $var2 = q{A more pleasant way of escaping.};
my $var3 = q(Others prefer parens as the quote mechanism.);

引用メカニズム:

q:リテラル引用。エスケープする必要がある文字のみが終了文字です。 qq:解釈された引用。変数とエスケープ文字を処理します。引用する必要がある文字列に最適:

my $var4 = qq{This "$mechanism" is broken.  Please inform "$user" at "$email" about it.};

qx:qqと同様に機能しますが、システムコマンドとして非対話的に実行します。標準出力から生成されたすべてのテキストを返します。 (リダイレクトは、OSでサポートされている場合にも出力されます)また、逆引用符( `文字)で行われます。

my $output  = qx{type "$path"};      # get just the output
my $moreout = qx{type "$path" 2>&1}; # get stuff on stderr too

qr:qqと同様に解釈しますが、正規表現としてコンパイルします。正規表現のさまざまなオプションも使用できます。これで、変数として正規表現を渡すことができます:

sub MyRegexCheck {
    my ($string, $regex) = @_;
    if ($string)
    {
       return ($string =~ $regex);
    }
    return; # returns 'null' or 'empty' in every context
}

my $regex = qr{http://[\w]\.com/([\w]+/)+};
@results = MyRegexCheck(q{http://myurl.com/subpath1/subpath2/}, $regex);

qw:非常に便利な引用演算子。引用符で囲まれた空白で区切られた単語のセットをリストに変換します。単体テストでデータを入力するのに最適です。


   my @allowed = qw(A B C D E F G H I J K L M N O P Q R S T U V W X Y Z { });
   my @badwords = qw(Word1 Word2 Word3 Word4);
   my @numbers = qw(one two three four 5 six seven); # works with numbers too
   my @list = ('string with space', qw(eight nine), "a $var"); # works in other lists
   my $arrayref = [ qw(and it works in arrays too) ]; 

それは物事を明確にするたびにそれらを使用するのは素晴らしいことです。 qx、qq、およびqには、ほとんどの場合{}演算子を使用します。 qwを使用する人々の最も一般的な習慣は通常()演算子ですが、qw //も表示される場合があります。

31
Robert P

「for」ステートメントは、Pascalで「with」を使用するのと同じ方法で使用できます。

for ($item)
{
    s/&‎nbsp;/ /g;
    s/<.*?>/ /g;
    $_ = join(" ", split(" ", $_));
}

変数名を繰り返すことなく、一連のs ///操作などを同じ変数に適用できます。

注:上記の非改行スペース(&nbsp;)は、マークダウンを回避するためにUnicodeを隠しています。コピーして貼り付けないでください:)

27
timkay

本当に隠されていませんが、Perlプログラマーは毎日多くのことを知りません [〜#〜] cpan [〜#〜] 。これは特に、フルタイムのプログラマーではないか、Perlでフルタイムでプログラミングしていない人に当てはまります。

27
mpeters

クォートワード演算子は、私のお気に入りの1つです。比較する:

my @list = ('abc', 'def', 'ghi', 'jkl');

そして

my @list = qw(abc def ghi jkl);

ノイズが少なく、目に優しい。 Perlについてのもう1つの本当に素晴らしいことは、SQLを書くときに本当に見逃していることです。末尾のコンマが有効であるということです。

print 1, 2, 3, ;

それは奇妙に見えますが、コードを別の方法でインデントした場合ではありません:

print
    results_of_foo(),
    results_of_xyzzy(),
    results_of_quux(),
    ;

関数呼び出しに追加の引数を追加する場合、前の行または末尾の行でカンマをいじる必要はありません。単一行の変更は、その周囲の行に影響を与えません。

これにより、可変機能を使用することが非常に快適になります。これはおそらくPerlの最も過小評価されている機能の1つです。

26
dland

[〜#〜] data [〜#〜]ブロックに直接貼り付けられたデータを解析する機能。プログラムなどで開くテストファイルに保存する必要はありません。例えば:

my @lines = <DATA>;
for (@lines) {
    print if /bad/;
}

__DATA__
some good data
some bad data
more good data 
more good data 
26
allan

バイナリ「x」は 繰り返し演算子 です。

print '-' x 80;     # print row of dashes

リストでも機能します:

print for (1, 4, 9) x 3; # print 149149149
24
Bruno De Fraine

新しいブロック操作

私は、言語を拡張し、擬似ブロック操作を作成する機能が1つだと思います。

  1. 最初にコード参照を取得することを示すサブルーチンのプロトタイプを宣言します。

    sub do_stuff_with_a_hash (&\%) {
        my ( $block_of_code, $hash_ref ) = @_;
        while ( my ( $k, $v ) = each %$hash_ref ) { 
            $block_of_code->( $k, $v );
        }
    }
    
  2. その後、次のように本体で呼び出すことができます

    use Data::Dumper;
    
    do_stuff_with_a_hash {
        local $Data::Dumper::Terse = 1;
        my ( $k, $v ) = @_;
        say qq(Hey, the key   is "$k"!);
        say sprintf qq(Hey, the value is "%v"!), Dumper( $v );
    
    } %stuff_for
    ;
    

Data::Dumper::Dumperはもう1つの半隠されたgemです。)ブロックの前にsubキーワードが必要ないこと、またはハッシュの前にカンマが必要ないことに注意してください。最終的には次のようになります:map { } @list

ソースフィルター

また、ソースフィルターもあります。 Perlがコードを渡して操作できるようにします。これとブロック操作の両方は、ほとんどの場合、自宅で試してはいけないタイプのものです。

ソースフィルターを使用して、たとえば、時間を確認するための非常に単純な言語を作成し、短いPerlワンライナーを使用して意思決定を行えるようにするなど、いくつかのすてきなことを行いました。

Perl -MLib::DB -MLib::TL -e 'run_expensive_database_delete() if $hour_of_day < AM_7';

Lib::TLは、「変数」と定数の両方をスキャンし、それらを作成し、必要に応じて置換します。

繰り返しになりますが、ソースフィルターは乱雑ですが、強力です。しかし、それらはデバッガーをひどく混乱させる可能性があります-そして、警告さえ間違った行番号で印刷される可能性があります。 Damianの Switch の使用を停止しました。これは、デバッガーが実際にどこにいるかを伝える能力をすべて失うためです。しかし、コードの小さなセクションを変更して同じ行に置くことで、被害を最小限に抑えることができることがわかりました。

シグナルフック

多くの場合、これで十分ですが、それほど明白ではありません。古いものに便乗するダイハンドラーを次に示します。

my $old_die_handler = $SIG{__DIE__};
$SIG{__DIE__}       
    = sub { say q(Hey! I'm DYIN' over here!); goto &$old_die_handler; }
    ;

つまり、コード内の他のモジュールが死ぬことを望むときはいつでも、彼らはあなたのところに来なければなりません(誰かが$SIG{__DIE__}に破壊的な上書きをしない限り)。そして、誰かが何かがエラーであることを通知することができます。

もちろん、クリーンアップするだけであれば、END { }ブロックを使用するだけで十分です。

overload::constant

モジュールを含むパッケージ内の特定のタイプのリテラルを検査できます。たとえば、import subでこれを使用する場合:

overload::constant 
    integer => sub { 
        my $lit = shift;
        return $lit > 2_000_000_000 ? Math::BigInt->new( $lit ) : $lit 
    };

つまり、呼び出しパッケージの20億を超える整数はすべてMath::BigIntオブジェクトに変更されます。 ( overload :: constant を参照)。

グループ化された整数リテラル

私たちがそれにいる間。 Perlを使用すると、大きな数値を3桁のグループに分割しても、そこから解析可能な整数を取得できます。上記の20億の2_000_000_000に注意してください。

24
Axeman

汚染チェック。汚染チェックを有効にすると、Perlは死にます(または、-t)汚染されたデータ(大まかに言うと、プログラムの外部からのデータ)を安全でない関数(ファイルを開く、外部コマンドを実行するなど)に渡そうとした場合。 setuidスクリプトやCGI、またはスクリプトがデータを供給する人よりも大きな特権を持っているものを書くときに非常に役立ちます。

魔法の後藤。 goto &subは、最適化された末尾呼び出しを行います。

デバッガー。

use strictおよびuse warnings。これらは、タイプミスからあなたを救うことができます。

24
Andru Luvisi

"-n"および"-p"スイッチはPerl 5に実装されています。}{

ls |Perl -lne 'print $_; }{ print "$. Files"'

内部的にこのコードに変換されます:

LINE: while (defined($_ = <ARGV>)) {
    print $_; }{ print "$. Files";
}
22
Sec

map -コードがより表現力豊かになるだけでなく、この「関数型プログラミング」についてもう少し読む衝動を与えたからです。

18
brunorc

Spaceship Operator で簡単に始めましょう。

$a = 5 <=> 7;  # $a is set to -1
$a = 7 <=> 5;  # $a is set to 1
$a = 6 <=> 6;  # $a is set to 0
18
Sec

これはメタ答えですが、 Perl Tips アーカイブには、Perlで実行できるあらゆる種類の興味深いトリックが含まれています。以前のヒントのアーカイブは閲覧のためにオンラインであり、メーリングリストまたはatomフィードを介して購読できます。

私のお気に入りのヒントには、 PARで実行可能ファイルをビルドするオートダイを使用して例外を自動的にスローする 、および switch および smart-match Perl 5.10のコンストラクト。

開示:私はPerl Tipsの著者であり、メンテナーでもあります。 ;)

18
pjf

ループのcontinue句。これは、次のループを含め、すべてのループの下部で実行されます。

while( <> ){
  print "top of loop\n";
  chomp;

  next if /next/i;
  last if /last/i;

  print "bottom of loop\n";
}continue{
  print "continue\n";
}
15
Shawn H Corey

私の投票は、Perlの正規表現の(?{})および(?? {})グループに行きます。最初は戻り値を無視してPerlコードを実行し、2番目は戻り値を正規表現として使用してコードを実行します。

15
Leon Timmermans
while(/\G(\b\w*\b)/g) {
     print "$1\n";
}

\ Gアンカー。 hotです。

13
J.J.

m//演算子には、いくつかのあいまいな特殊なケースがあります。

  • ?を区切り文字として使用すると、resetを呼び出さない限り、1回だけ一致します。
  • 'を区切り文字として使用すると、パターンは補間されません。
  • パターンが空の場合、最後に一致したパターンを使用します。
13
Michael Carman

Nullファイルハンドル ダイヤモンド演算子<>は、コマンドラインツールの構築に適しています。 <FH>は、最初に見つかったコマンドラインファイル名またはSTDINのいずれかを魔法のように選択することを除いて、ハンドルから読み取ります。 perlopから取得:

while (<>) {
...         # code for each line
}
12
spoulson

特別なコードブロックBEGINCHECKENDなど。 Awkから来ていますが、Perlではレコードベースではないため、動作が異なります。

BEGINブロックを使用して、解析フェーズのコードを指定できます。また、構文と変数のチェックを行うときにも実行されますPerl -c。たとえば、構成変数を読み込むには:

BEGIN {
    eval {
        require 'config.local.pl';
    };
    if ($@) {
        require 'config.default.pl';
    }
}
11
Bruno De Fraine
rename("$_.part", $_) for "data.txt";

自分自身を繰り返すことなく、data.txt.partをdata.txtに名前変更します。

11
timkay

少しあいまいなのは、スカラーコンテキストを強制するチルダチルダ「演算子」です。

print ~~ localtime;

と同じです

print scalar localtime;

とは異なります

print localtime;
10
Sec

スタックをルックアップして一致するラベルを見つけるPerlのループ制御構造の「デスペレーションモード」により、Test :: Moreが好むと好まざるとにかかわらない奇妙な動作が可能になります。

SKIP: {
    skip() if $something;

    print "Never printed";
}

sub skip {
    no warnings "exiting";
    last SKIP;
}

ほとんど知られていない.pmcファイルがあります。 「use Foo」は、Foo.pmの前に@INCでFoo.pmcを探します。これは、コンパイルされたバイトコードを最初にロードできるようにすることを目的としていましたが、 Module :: Compile は、これを利用してソースフィルタリングされたモジュールをキャッシュし、ロード時間を短縮してデバッグを容易にします。

警告をエラーに変換する機能。

local $SIG{__WARN__} = sub { die @_ };
$num = "two";
$sum = 1 + $num;
print "Never reached";

それは言及されていない私の頭の上から考えることができます。

9
Schwern

ヤギのoperator*

$_ = "foo bar";
my $count =()= /[aeiou]/g; #3

または

sub foo {
    return @_;
}

$count =()= foo(qw/a b c d/); #4

スカラーコンテキストでのリストの割り当てにより、割り当てられるリスト内の要素の数が得られるため、機能します。

*注、実際には演算子ではない

9
Chas. Owens

入力レコード区切り文字は、固定長レコードを読み取るための数値への参照に設定できます。

$/ = \3; print $_,"\n" while <>; # output three chars on each line
9
shmem

tie、変数結合インターフェース。

9
davidnicol

これは特に便利というわけではありませんが、非常に難解です。 Perlパーサーを掘り下げながら、私はこれにつまずいた。

PODが登場する前は、Perl4には、manページをnroffとしてプログラムに直接埋め込み、失われないようにするトリックがありました。 Perl4は wrapman (詳細については319ページのピンクキャメルを参照)と呼ばれるプログラムを使用して、nroffのマニュアルページをスクリプトに巧みに埋め込みました。

すべてのコードを無視するようにnroffに指示し、Perlに指示する[〜#〜] end [〜#〜]タグの後にマニュアルページの内容を配置することで機能しましたコードの処理を停止します。このようなものに見えた:

#!/usr/bin/Perl
'di';
'ig00';

...Perl code goes here, ignored by nroff...

.00;        # finish .ig

'di         \" finish the diversion
.nr nl 0-1  \" fake up transition to first page
.nr % 0     \" start at page 1
'; __END__

...man page goes here, ignored by Perl...

Roffマジックの詳細は私を逃がしますが、roffコマンドはvoidコンテキストの文字列または数字であることに気付くでしょう。通常、voidコンテキストの定数は警告を生成します。 op.cには、特定のroffコマンドで始まるvoidコンテキスト文字列を許可する特別な例外があります。

              /* Perl4's way of mixing documentation and code
                 (before the invention of POD) was based on a
                 trick to mix nroff and Perl code. The trick was
                 built upon these three nroff macros being used in
                 void context. The pink camel has the details in
                 the script wrapman near page 319. */
                const char * const maybe_macro = SvPVX_const(sv);
                if (strnEQ(maybe_macro, "di", 2) ||
                    strnEQ(maybe_macro, "ds", 2) ||
                    strnEQ(maybe_macro, "ig", 2))
                        useless = NULL;

つまり、'di';は警告を生成しませんが、'die';'did you get that thing I sentcha?';または'ignore this line';も生成しません。

また、数値定数0および1には例外があり、裸の.00;が許可されます。コードは、これがより一般的な目的のためであると主張しています。

            /* the constants 0 and 1 are permitted as they are
               conventionally used as dummies in constructs like
                    1 while some_condition_with_side_effects;  */
            else if (SvNIOK(sv) && (SvNV(sv) == 0.0 || SvNV(sv) == 1.0))
                useless = NULL;

そして、あなたは何を知っていますか、2 while conditionは警告します!

7
Schwern

@ {[...]}を使用して、複雑なPerl式の補間結果を取得できます。

$a = 3;
$b = 4;

print "$a * $b = @{[$a * $b]}";

プリント:3 * 4 = 12

7
user105090

難解なのかわかりませんが、私のお気に入りの1つは ハッシュスライス です。私はあらゆるものにそれを使用しています。たとえば、2つのハッシュをマージするには:

 my%number_for =(one => 1、two => 2、three => 3); 
 my%your_numbers =(two => 2、four => 4、six => 6 ); 
 @ number_for {keys%your_numbers} = values%your_numbers; 
 sort sort values%number_for; #12346 
7
Vince Veselosky
use diagnostics;

Perlを使い始めたことがあり、これまで一度も行ったことがない場合、このモジュールは時間と手間を大幅に節約します。取得できるほぼすべての基本的なエラーメッセージについて、このモジュールは、コードが壊れている理由についての長い説明を提供します。修正方法についての役立つヒントも含まれます。例えば:

use strict;
use diagnostics;

$var = "foo";

この役立つメッセージが表示されます:

グローバルシンボル「$ var」には、4行目の明示的なパッケージ名が必要です。
の実行-コンパイルエラーのために中止(#1)
(F)厳密な変数を使用します。これは、すべての変数
がレキシカルスコープ(「my」を使用)、事前に
「our」を使用して宣言されている、またはグローバル変数をどのパッケージ.____。]は(「::」を使用)にあります。
 
ユーザーコードからのキャッチされない例外:
グローバルシンボル "$ var"には、4行目の明示的なパッケージ名が必要です。 
の実行-コンパイルエラーのため中止されました。
 at-行5 
use diagnostics;
use strict;

sub myname {
    print { " Some Error " };
};

この大きくて役立つテキストの塊が得られます:

構文エラー-5行目、「};」付近
の実行-コンパイルエラーにより中止(#1)
(F)おそらく構文エラーが発生したことを意味します。一般的な理由は次のとおりです。
 
キーワードのつづりが間違っています。
セミコロンがありません。
カンマがありません。
開き括弧または閉じ括弧がありますmissing。
開き括弧または閉じ括弧がありません。
閉じ引用符がありません。
 
多くの場合、構文に関連する別のエラーメッセージが表示されます
詳細情報の提供エラー。 (場合によっては-wを有効にするのに役立ちます。) Perlはランダム入力を理解するのが得意であるため、実際のエラーはいくつかのトークン
である場合があります。
時折、行番号が誤解を招く可能性があり、青い月に一度だけ
エラーの原因を特定する方法は、
 Perl -cを繰り返し呼び出して、毎回プログラムの半分を切り取り、エラーがなくなったかどうかを確認することです
。 S。
 
のサイバネティックバージョンのソートユーザーコードからのキャッチされない例外:
構文エラー-5行目、「};」付近
実行-中止コンパイルエラーのため。
 at-行7 

そこから、プログラムの何が問題なのかを推測することができます(この場合、印刷はまったく間違ってフォーマットされています)。診断には多くの既知のエラーがあります。現在、これは本番環境で使用するのは良いことではありませんが、Perlを初めて使用する人にとっては優れた学習補助として役立ちます。

6
Robert P
sub load_file
{
    local(@ARGV, $/) = shift;
    <>;
}

必要に応じて配列を返すバージョン:

sub load_file
{
    local @ARGV = shift;
    local $/ = wantarray? $/: undef;
    <>;
}
6
timkay

($ x、$ y)=($ y、$ x)は、Perlを学びたいと思った理由です。

リストコンストラクター1..99または 'a' .. 'zz'も非常にいいです。

5
Daniel

@Schwernは、$SIG{__WARN__}をローカライズすることにより、警告をエラーに変換することに言及しました。 use warnings FATAL => "all";を使用して(字句的に)これを行うこともできます。 perldoc lexwarnを参照してください。

そのメモでは、Perl 5.12以降、完全なperldoc fooの代わりにperldoc perlfooと言うことができました。最後に! :)

5
wolverian

配列の開始インデックスを決定する変数$ [もあります。デフォルトは0なので、配列は0から始まります。

$[=1;

本当にしたい場合は、Perlを [〜#〜] awk [〜#〜] (またはFortran)のように動作させることができます。

5
Sec

左辺値を使用して、コードを本当に混乱させます。

my $foo = undef ;
sub bar:lvalue{ return $foo ;}

# Then later

bar = 5 ;
print bar ;
4
Jeteve

文字列またはリストを条件付きで他のリストに追加するための便利な複合演算子の1つは、x!!オペレーター:

 print 'the meaning of ', join ' ' =>  
     'life,'                x!! $self->alive,
     'the universe,'        x!! ($location ~~ Universe),
     ('and', 'everything.') x!! 42; # this is added as a list

この演算子は、次のような逆の構文を許可します

 do_something() if test();
4
Eric Strom

大丈夫。ここに別のものがあります。 動的スコープ 。別の投稿で少し語られましたが、隠された機能についてはここでは見ませんでした。

Autovivificationのような動的スコープは、それを使用する言語が非常に限られています。 PerlとCommon LISPは、ダイナミックスコーピングを使用していることを私が知っている唯一の2つです。

4
J.J.

使用能力はどうですか

my @symbols = map { +{ 'key' => $_ } } @things;

配列からハッシュリファレンスの配列を生成する-ハッシュリファレンスの前にある+はブロックを明確にするため、インタープリターはコードブロックではなくハッシュリファレンスであることを認識します。驚くばかり。

(トロントのPerlmongersミーティングでこれを説明してくれたDave Doyleに感謝します。)

4
talexb

安全なコンパートメント。

Safeモジュールを使用すると、Perlのみを使用して独自のサンドボックススタイルの環境を構築できます。その後、Perlスクリプトをサンドボックスにロードできます。

宜しくお願いします、

4
melo

コア IO::Handle モジュール。私にとって最も重要なことは、ファイルハンドルの自動フラッシュを許可することです。例:

use IO::Handle;    
$log->autoflush(1);
4

このワンライナーは、globを使用して、指定された長さ(4)の単語に対してアルファベット(A、T、C、およびG-> DNA)のすべての単語の組み合わせを生成する方法を示しています。

Perl -MData::Dumper -e '@CONV = glob( "{A,T,C,G}" x 4 ); print Dumper( \@CONV )'
4
maasha

Quantum::Superpositions

use Quantum::Superpositions;

if ($x == any($a, $b, $c)) { ...  }
3
Dario

_use re debug_
デバッグの使用に関するドキュメント

そして

_Perl -MO=Concise[,OPTIONS]_
簡潔なドキュメント

C、Pascal、Pythonおよびその他の言語のスタイルでのプログラミングに非常に柔軟で、表現力があり、受け入れやすいことに加えて、Perlを最初のkanoodlingの「後藤」言語にするプラグマコマンドスイッチがいくつかありますアルゴリズム、正規表現、または解決が必要な迅速な問題これらの2つは、Perlに固有のものであり、私のお気に入りの1つです。

_use re debug_:正規表現の最新のフレーバーは、Perlに現在の形式と機能を負っています。他の言語で表現できない正規表現のPerl形式は数多くありますが、Perlで表現できない正規表現の他の言語の形式はほとんどありません。さらに、Perlには素晴らしい正規表現デバッガーが組み込まれており、正規表現エンジンがどのように正規表現を解釈し、ターゲット文字列と照合するかを示します。

例:最近、簡単なCSVルーチンを作成しようとしていました。 (はい、はい、私は知っています、私は Text :: CSV ... を使用していたはずですが、CSV値は引用されておらず、単純ではありませんでした。

最初のテイクは、/^(^(?:(.*?),){$i}/で、n個のCSVレコードからiレコードを抽出しました。最後のレコードまたはnのnを除き、これは正常に機能します。デバッガなしでそれを見ることができました。

次に/^(?:(.*?),|$){$i}/を試してみましたが、これは機能せず、その理由がすぐにわかりませんでした。 _(.*?)_の後にコンマまたはEOLが続いていると思っていた。次に、小さなテストスクリプトの先頭に_use re debug_を追加しました。ああ、そうです、_,|$_間の変更はそのように解釈されていませんでした。それは_((.*?),) | ($)_として解釈されていました-私が望んでいたものではありませんでした。

新しいグループ化が必要でした 。それで私は/^(?:(.*?)(?:,|$)){$i}/に到達しました。正規表現デバッガーにいる間、文字列の終わりに向かって一致するまでにループがいくつかかったかに驚きました。 _.*?_という用語は非常にあいまいであり、満たすために過度のバックトラックを必要とします。だから私は/^(?:(?:^|,)([^,]*)){$i}/を試しました。1)コンマ以外のすべての貪欲なマッチのためにバックトラッキングを減らします。2)正規表現オプティマイザーが最初のフィールドで一度だけ変更を使用できるようにしました。ベンチマークを使用すると、これは最初の正規表現よりも35%高速です。正規表現デバッガーは素晴らしく、ほとんど使用していません。

_Perl -MO=Concise[,OPTIONS]_:BおよびConciseフレームワークは、Perlがあなたの傑作をどのように解釈しているかを見るための素晴らしいツールです。 _-MO=Concise_を使用すると、ソースコードのPerlインタープリター翻訳の結果が出力されます。 Conciseには多くのオプションがあり、Bでは、OPコードの独自のプレゼンテーションを作成できます。

この投稿 のように、Conciseを使用して異なるコード構造を比較できます。ソース行を生成するOPコードでソース行をインターリーブできます。見てみな。

3
dawg

パーティーにとても遅れましたが、属性:.

基本的に属性を使用すると、変数またはサブルーチンの宣言に関連付ける任意のコードを定義できます。これらを使用する最良の方法は、 Attribute :: Handlers ;を使用することです。これにより、属性を定義するのが簡単になります(他の属性に関しては!)。

YAPC :: 2006、オンライン here で、プラグ可能なクラスとそのプラグインを宣言的にアセンブルするためにそれらを使用するプレゼンテーションを行いました。これは非常にユニークな機能です。

3
Joe McMahon

私は個人的にs ///操作に対する/ e修飾子が大好きです:

while(<>) {
  s/(\w{0,4})/reverse($1);/e; # reverses all words between 0 and 4 letters
  print;
}

入力:

This is a test of regular expressions
^D

出力(私は思う):

sihT si a tset fo regular expressions
3
Chris Lutz

HEREDOCSで異なる引用符を使用して、異なる動作を取得できます。

my $interpolation = "We will interpolated variables";
print <<"END";
With double quotes, $interpolation, just like normal HEREDOCS.
END

print <<'END';
With single quotes, the variable $foo will *not* be interpolated.
(You have probably seen this in other languages.)
END

## this is the fun and "hidden" one
my $Shell_output = <<`END`;
echo With backticks, these commands will be executed in Shell.
echo The output is returned.
ls | wc -l
END

print "Shell output: $Shell_output\n";
3
Justin

プログラムの構文エラーをチェックするより強力な方法があります。

Perl -w -MO=Lint,no-context myscript.pl

できる最も重要なことは、「存在しないサブルーチン」エラーの報告です。

3
Alexey

Perlの私のお気に入りの半隠し機能はeof関数です。以下は、perldoc -f eofからの直接的な例です。これを使用して、コマンドラインでロードされた複数のファイルでファイル名と$.(現在の行番号)を簡単にリセットできます。

while (<>) {
  print "$ARGV:$.\t$_";
} 
continue {
  close ARGV if eof
}
3
Telemachus

正規表現と文字列の区切り文字は、他のものに置き換えることができます。これは、「つまようじ症候群」に特に役立ちます。以下に例を示します。

$url =~ /http:\/\/www\.stackoverflow\.com\//;

区切り文字を変更することで、ほとんどの逆打を排除できます。 /bar/m/bar/の省略形で、m!bar!と同じです。

$url =~ m!http://www\.stackoverflow\.com/!;

{}や[]のようなバランスの取れた区切り文字を使用することもできます。私は個人的にこれらが大好きです。 q{foo}'foo'と同じです。

$code = q{
    if( this is awesome ) {
        print "Look ma, no escaping!";
    }
};

友達(および構文ハイライター)を混乱させるには、これを試してください:

$string = qq'You owe me $1,000 dollars!';
3

Axemanは、いくつかの組み込み関数を簡単にラップできることを思い出しました。

Perl 5.10より前は、PerlにはPythonのようなきれいな印刷(たとえば)がありませんでした。

ローカルプログラムでは、次のようなことができます。

sub print {
     print @_, "\n";
}

または、デバッグを追加します。

sub print {
    exists $ENV{DEVELOPER} ?
    print Dumper(@_) :
    print @_;
}
2
J.J.

以下は短いものですが、「~~」よりも意味があります。何が返されるかを示し、スマートマッチ演算子と混同しないためです。

print "".localtime;   # Request a string

print 0+@array;       # Request a number
2
ikegami

ループ内で見られるフィルターとしてハッシュを使用する機能。別の言語でニースのようなものをまだ見ていません。たとえば、私はこれをPythonで複製することができませんでした。

たとえば、前に見​​たことがない場合に行を印刷したい。

my %seen;

for (<LINE>) {
  print $_ unless $seen{$_}++;
}
2
Jauder Ho

うまく機能する2つのこと:IOコア内文字列のハンドル、および関数プロトタイプを使用してgrep/mapのような構文で独自の関数を作成できるようにします。

sub with_output_to_string(&) {           # allows compiler to accept "yoursub {}" syntax.
  my $function = shift;
  my $string   = '';
  my $handle   = IO::Handle->new();
  open($handle, '>', \$string) || die $!; # IO handle on a plain scalar string ref
  my $old_handle = select $handle;
  eval { $function->() };
  select $old_handle;
  die $@ if $@;
  return $string;
}

my $greeting = with_output_to_string {
  print "Hello, world!";
};

print $greeting, "\n";
2
Danny Woods

私が一番気に入っている機能は、ステートメント修飾子です。

何回やりたいかわからない:

say 'This will output' if 1;
say 'This will not output' unless 1;
say 'Will say this 3 times. The first Time: '.$_ for 1..3;

他の言語で。等...

「など」は、5.12のもう1つの機能、Yada Yadaオペレーターを思い出させました。

これは、プレースホルダーが必要な場合に最適です。

sub something_really_important_to_implement_later {
    ...
} 

それをチェックしてください: Perl Docs on Yada Yada Operator

2
gdey

コマンドラインの新しい-Eオプション:

> Perl -e "say 'hello"" # does not work 

String found where operator expected at -e line 1, near "say 'hello'"
        (Do you need to predeclare say?)
syntax error at -e line 1, near "say 'hello'"
Execution of -e aborted due to compilation errors.

> Perl -E "say 'hello'" 
hello
2
knb

たとえば、文字列内の関数呼び出しを展開できます。

print my $foo = "foo @{[scalar(localtime)]} bar";

foo Wed May 26 15:50:30 2010 bar

2
trapd00r

一致正規表現の補間。これの便利なアプリケーションは、ブラックリストで照合する場合です。補間を使用しない場合、次のように記述されます。

#detecting blacklist words in the current line
/foo|bar|baz/;

代わりに書くことができます

@blacklistWords = ("foo", "bar", "baz");
$anyOfBlacklist = join "|", (@blacklistWords);
/$anyOfBlacklist/;

これはより冗長ですが、データファイルからの入力が可能です。また、何らかの理由でリストがソースで保持されている場合は、RegExpよりも配列を保持する方が簡単です。

1
Erick

ハッシュ(キーは一意)を使用して、リストの一意の要素を取得します。

my %unique = map { $_ => 1 } @list;
my @unique = keys %unique;
1
Nick Dixon

メモリを節約するためにこれを行うことができると思うかもしれません:

@is_month{qw(jan feb mar apr may jun jul aug sep oct nov dec)} = undef;

print "It's a month" if exists $is_month{lc $mon};

しかし、それはしません。 Perlは依然として各キーに異なるスカラー値を割り当てます。 Devel :: Peek はこれを示しています。 PVHVはハッシュです。 Eltはキーであり、その後に続くSVはその値です。各SVには、共有されていないことを示す異なるメモリアドレスがあることに注意してください。

Dump \%is_month, 12;

SV = RV(0x81c1bc) at 0x81c1b0
  REFCNT = 1
  FLAGS = (TEMP,ROK)
  RV = 0x812480
  SV = PVHV(0x80917c) at 0x812480
    REFCNT = 2
    FLAGS = (SHAREKEYS)
    ARRAY = 0x206f20  (0:8, 1:4, 2:4)
    hash quality = 101.2%
    KEYS = 12
    FILL = 8
    MAX = 15
    RITER = -1
    EITER = 0x0
    Elt "feb" HASH = 0xeb0d8580
    SV = NULL(0x0) at 0x804b40
      REFCNT = 1
      FLAGS = ()
    Elt "may" HASH = 0xf2290c53
    SV = NULL(0x0) at 0x812420
      REFCNT = 1
      FLAGS = ()

Undefスカラーは整数スカラーと同じ量のメモリを使用するため、すべてを1に割り当てるだけでよく、existsでチェックするのを忘れないようにできます。

my %is_month = map { $_ => 1 } qw(jan feb mar apr may jun jul aug sep oct nov dec);

print "It's a month" if $is_month{lc $mon});
1
timkay

次回、オタクパーティーに行くときは、このワンライナーをbashシェルで引き出してください。女性があなたを群がらせ、あなたの友人があなたを崇拝します:

見つける 。 -name "* .txt" | xargs Perl -pi -e 's/1:(\ S +)/ uc($ 1)/ ge'

すべての* .txtファイルを処理し、Perlの正規表現を使用してインプレース検索および置換を実行します。これは、「1:」の後のテキストを大文字に変換し、「1:」を削除します。 Perlの「e」修飾子を使用して、検索/置換正規表現の2番目の部分を実行可能コードとして扱います。インスタント1行テンプレートシステム。 xargsを使用すると、bashのコマンドラインの長さ制限に達することなく、膨大な数のファイルを処理できます。

1
Mark Maunder

表現 defined &DB::DBは、プログラムがデバッガー内から実行されている場合にtrueを返します。

1
Kiffin

Unpack()およびpack()関数に1つ追加します。これらは、他のプログラムで使用される形式でデータをインポートおよび/またはエクスポートする必要がある場合に便利です。

もちろん最近では、ほとんどのプログラムでデータをXMLでエクスポートできます。また、一般的に使用される多くの独自のドキュメント形式には、Perlモジュールが関連付けられています。しかし、これは必要なときに非常に便利な機能の1つであり、pack()/ unpack()はおそらくreasonであり、人々は非常に多くの独自のデータ形式のCPANモジュールを書くことができます。

1
Peter

私はパーティーに少し遅れましたが、組み込みのtie-hash関数dbmopen()への投票-それは私を大いに助けました。正確にはデータベースではありませんが、データをディスクに保存する必要がある場合、多くの問題が取り除かれ、機能します。データベースを持っていなかったり、Storable.pmを理解していなかったので、始めるのに役立ちましたが、テキストファイルの読み取りと書き込みを超えて前進したいと思っていました。

1
AmbroseChapel

B :: Deparse -Perlコードを生成するPerlコンパイラバックエンド。日常のPerlコーディングで使用するものではありませんが、特別な状況では役立つ可能性があります。

難読化されたコードや複雑な式に遭遇した場合は、Deparseを介して渡します。ゴルフされるJAPHまたはPerlコードを把握するのに役立ちます。

$ Perl -e '$"=$,;*{;qq{@{[(A..Z)[qq[0020191411140003]=~m[..]g]]}}}=*_=sub{print/::(.*)/};$\=$/;q<Just another Perl Hacker>->();'
Just another Perl Hacker

$ Perl -MO=Deparse -e '$"=$,;*{;qq{@{[(A..Z)[qq[0020191411140003]=~m[..]g]]}}}=*_=sub{print/::(.*)/};$\=$/;q<Just another Perl Hacker>->();'
$" = $,;
*{"@{[('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z')['0020191411140003' =~ /../g]];}";} = *_ = sub {
    print /::(.*)/;
}
;
$\ = $/;
'Just another Perl Hacker'->();
-e syntax OK

より有用な例は、deparseを使用して、別のモジュールから受け取った可能性のあるcoderefの背後にあるコードを見つけることです。

use B::Deparse;
my $deparse = B::Deparse->new;
$code = $deparse->coderef2text($coderef);
print $code;
0
Prakash K

裸のブロックをredoまたは他の制御ワードとともに使用して、カスタムループ構造を作成します。

オブジェクトのリンクリストを走査して、最初の->can('print')メソッドを返します:

sub get_printer {
    my $self = shift;
    {$self->can('print') or $self = $self->next and redo}
}
0
Eric Strom

もう1つ...

Perlキャッシュ:

my $processed_input = $records || process_inputs($records_file);

Elpelegオープンソース、Perl CMSで http://www.web-app.net/

0
On Elpeleg

同じ行に印刷して、スクリプトの進行状況を表示します。

$| = 1; # flush the buffer on the next output 

for $i(1..100) {
    print "Progress $i %\r"
}
0
Tomasz

Perlは柔軟なawk/sedとして優れています。

たとえば、ls | xargs statの単純な置換を使用できます。

$ ls | Perl -pe 'print "stat "' | sh 

入力(ファイル名)にスペースまたは|$\などのシェル特殊文字が含まれる場合、これはうまく機能しません。そのため、Perl出力では単一引用符が頻繁に必要になります。

コマンドライン-neを介してPerlを呼び出す場合の複雑な点の1つは、シェルがワンライナーで最初にニブルを取得することです。これは、しばしばそれを満足させるための拷問的な脱出につながります。

私がいつも使用している「隠された」機能の1つは、シェルエスケープ\x27を使用する代わりに、単一引用符を含める'\''です。

そう:

$ ls | Perl -nle 'chomp; print "stat '\''$_'\''"' | sh

より安全に記述できます:

$ ls | Perl -pe 's/(.*)/stat \x27$1\x27/' | sh

ファイル名に変な文字が含まれていても、そのように引用されていても機能しません。しかし、これは:

$ ls | Perl -pe 's/\n/\0/' | xargs -0 stat
0
Terry

「今」

sub _now { 
        my ($now) = localtime() =~ /([:\d]{8})/;
        return $now;
}

print _now(), "\n"; #  15:10:33
0
Jet

@Corion-PerlのベアURL?もちろん、補間された文字列でも可能です。重要なのは、実際に正規表現として使用している文字列内だけです。

0
Toby

$ 0は、実行されているPerlスクリプトの名前です。モジュールを実行しているコンテキストを取得するために使用できます。

# MyUsefulRoutines.pl

sub doSomethingUseful {
  my @args = @_;
  # ...
}

if ($0 =~ /MyUsefulRoutines.pl/) {
  # someone is running  Perl MyUsefulRoutines.pl [args]  from the command line
  &doSomethingUseful (@ARGV);
} else {
  # someone is calling  require "MyUsefulRoutines.pl"  from another script
  1;
}

このイディオムは、他のスクリプトにインポートできるライブラリにいくつかの有用なサブルーチンを備えたスタンドアロンスクリプトを扱うのに役立ちます。 Pythonはobject.__== "__main__"イディオム。

0
mob