12

私はPerlを始めたばかりで(文字通り今日)、BeginningPerlの無料のオンラインバージョンを読んでいます。早い段階で、本は二重引用符で囲まれた文字列が補間されると述べました。ただし、print関数を使用するすべての例(これまでのところ...私は66ページ前後です)では、作成者はスカラー変数をリストパラメーターとして渡しています。たぶん私は銃をジャンプしているので、これについては後で説明しますが、方法Bよりも方法Aを選択する理由はありますか?

方法A:

$myVar = "value";
print "Current value is ", $myVar, "\n";

方法B:

$myVar = "value";
print "Current value is $myVar\n";

私の意見では、方法Bの方が便利です。コミュニティで好ましい方法はありますか?あるいは、ある方法を他の方法よりも安全に使用できるようにする隠れた落とし穴などがありますか?

TIA

4

10 に答える 10

14

確かに隠された落とし穴があります-perlは単純な変数名と次のような式を扱います

"$array[$subscript]"

"$hashref->{key}"

問題なく。ただし、式がますます複雑になるにつれて、最終的にperlは式がどこで停止し、文字列の残りの部分が開始するかを判断できなくなります。

この論文には、二重引用符で囲まれた文字列の変数補間(元々はここにありましたが、現在はダウンしています)には多くの厄介な詳細があります

于 2009-11-17T19:36:19.867 に答える
12

補間で注意すべき点がいくつかありますが、一度知ってしまえば、誤って行うことはほとんどありません。

有効な識別子テキストの横に変数名を配置します。Perlは最も長い有効な変数名を見つけ、それが以前に定義されているかどうかを気にしません。変数名の部分を中かっこで区切って明示的にすることができます。

  my $p = 'p';
  print "Mind your $ps and qs\n";  # $ps, not $p

  print "Mind your ${p}s and qs";  # now its $p

さて、その例では、アポストロフィを忘れました。追加すると、アポストロフィが昔からパッケージセパレータであったため、別の問題が発生しますが、それでも機能します。中かっこもそこで機能します。

  my $p = 'p';
  print "Mind your $p's and q's\n";  # $p::s, not $p

  print "Mind your ${p}'s and q's";  # now its $p

Perlは、ハッシュと配列への単一要素アクセスを補間することもできるため、変数名の横にインデックス文字を配置すると、望ましくないことが行われる可能性があります。

 print "The values are $string[$foo]\n";  That's the element at index $foo
 print "The values are $string{$foo}\n";  That's the value for the key $foo

文字列に電子メールアドレスが必要な場合、Perlが配列を補間するのを忘れる可能性があります。Perlは、@:をエスケープしない限り、これを致命的なエラーにしていました。

 print "Send me mail at joe@example.com\n";  # interpolates @example

 print "Send me mail at joe\@example.com\n";

Perlはバックスラッシュを使用して一部の文字をエスケープするため、リテラル文字が必要な場合はそれらを2倍にする必要があります。

 print "C:\real\tools\for\new\work";      # not what you might expect

 print "C:\\real\\tools\\for\\new\\work"; # kinda ugly, but that's life
 print "C:/real/tools/for/new/work";      # Windows still understands this

これらの小さな落とし穴にもかかわらず、別の言語を使用する必要がある場合に、Perlで文字列を簡単に作成できることを本当に懐かしく思っています。

于 2009-11-17T20:58:50.137 に答える
12

このような単純な例では、いいえ。ただし$myVar、ハッシュ参照の深い間接参照やメソッド呼び出しなど、実際にはもっと複雑なものであるかどうかを検討してください。文字列内を補間するものもありますが(ほとんどのオブジェクト参照は補間します)、メソッド呼び出しは補間しません。また、配列は、直接出力される場合と文字列に補間される場合で異なる動作をします。

PS。Perlへようこそ。旅を楽しんでください!:)

于 2009-11-17T19:25:08.483 に答える
12

落とし穴があります'

$owner = "John";
$item = "motorcycle".
print "This is $owner's $item.\n";  # Oops, parsed as $owner::s

しかし、上記は安全に次のように書くことができます

print "This is ${owner}'s $item.\n";
于 2009-11-17T19:41:06.907 に答える
4

方法Aは次のようになります。

$myVar = "value";
print 'Current value is ', $myVar, "\n";

文字列を一重引用符で囲む場合、Perlは補間するものを探すために全体をわざわざ読み取ることはありません。したがって、補間を必要としない長い文字列がある場合は、一重引用符を使用して動的部分を追加する方が速い場合があります。 、上記のように。

ただし、これはマイクロ最適化であり、実際には大きな違いはありません。

方法Aを使用する別のケースは、文字列にエスケープ文字が含まれている場合で、わざわざエスケープしたくない場合です。

$myVar = 12000;
print 'Conversion from $US to $CND: ', $myVar,\n";

この場合、Perlに変数$US$CND変数を検索させたくはありません。文字列にドル記号を含めるだけです。

結局、それは主にスタイルの問題です。私は通常、必要がない限り、二重引用符で囲まれた文字列を避けようとします。

于 2009-11-17T19:25:46.620 に答える
3

補間の落とし穴について話しているので、補間を避けるために一重引用符で囲まれた文字列を使用している場合でも、末尾のスラッシュをエスケープする必要があることに注意してください。

'c:\files\'  #parse error
'c:\files\\' #correct

これは、最初の文字列の最後の文字が、文字列ターミネータではなく、エスケープされた一重引用符のように見えるためです。また、エスケープされたスラッシュは、引用符で囲まれた文字列の単一のスラッシュに変換されます

于 2009-11-17T20:04:42.597 に答える
2

あなたがPerlに手を伸ばしているのなら、あなたは物事を成し遂げるための最も速い方法を探しています。さらに、あなたは自分の考え方に最も似た方法でそれを行うことが奨励されています(したがって、Perlのモットー:TMTOWTDI、それを行うには複数の方法があります)。したがって、書くのが簡単な方法、後でコードに戻ったときに理解する可能性が最も高い方法は、それを実行する方法です(意図した結果を与えるなど、他のすべてのことは同じです) )。

あなたが示唆するように、あなたが「安全」について心配しているなら、汚染について学びましょう。それは、外界からの潜在的にいたずらなデータからあなたを守るのに役立ちます。

于 2009-11-17T19:23:55.680 に答える
1

(これはおそらくコミュニティウィキであるはずです。)

私の頭に浮かぶ唯一の明らかな問題は、配列の補間です。比較

print @arr, "\n";

print "@arr\n";

また、複雑な間接参照が補間ではうまく機能しない場合もありますが、それらはまれです。

于 2009-11-17T19:21:17.307 に答える
0

Perl固有のエディターとその強調表示機能に精通していないPerlの部外者として、私は可能な限り一重引用符を使用することに投票します。これにより、この文字列には補間されるものが何も含まれていないことが読者に明確になります。

于 2009-11-17T19:31:25.010 に答える
0

補間は、大幅な簡略化と時間の節約になります。しかし、行き過ぎてしまう可能性があります。

必要に応じて、補間を使用して奇妙なことを行うことができます。

@foo = 0..10;
print "$foo[2*3]"; # prints 6

そして、エキサイティングな任意の補間のために、この忌まわしきものを使うことができます:

print "@{[ some_function_call('in list context') ]}";

本当に補間された関数呼び出しを機能させたい場合は、そのためのモジュールがあります。Interpolationをチェックしてください。それはあなたがこのようなことをすることを可能にします:

use Interpolation;
print "I like $eval{ what_I_like() };

sub what_like_like {
    return 'pie';
}

そして、はるかに。

このモジュールの背景については、Identity.pm:A Very Funny ModuleandInterpolation参照してください。

于 2009-11-18T02:34:02.900 に答える