2

Perl / Tkコードで、次のような条件文を見つけました

if (s/^\+//)
{
   #do something
}
elsif (/^-/)
{
   #do another thing
}

いくつかのパターンマッチングが行われたようです。でも理解できません。誰かがこのパターンマッチングを理解するのを手伝ってもらえますか?

4

4 に答える 4

12

どちらも正規表現です。それらについてはperlreperlretutで読むことができます。http://www.rubular.comでそれらを試すことができます。

どちらも暗黙的に で何かを行い$_ます。おそらく、ループ変数のないコード行の周りにwhileorがあります。foreachその場合、$_そのループ変数になります。たとえば、読み取られているファイルの現在の行が含まれている場合があります。

  1. の現在の値に、文字列の先頭の最初の文字として (プラス) 記号が$_含まれている場合、 .+#do somehting
  2. -それ以外に(マイナス) 記号が含まれている場合は、 #do another thing.

ケース 1. では、その記号も何も置き換え+ません (つまり、削除します)。ただし、2.の場合は削除しません-


YAPE::Regex::Explainで説明を見てみましょう。

use YAPE::Regex::Explain;
print YAPE::Regex::Explain->new(qr/^\+/)->explain();

ここにあります。私たちの場合はあまり役に立ちませんが、それでも優れたツールです。(?-imsxとの)部分は、Perl が意味するデフォルトのものであることに注意してください。変更しない限り、常にそこにあります。

The regular expression:

(?-imsx:^\+)

matches as follows:

NODE                     EXPLANATION
----------------------------------------------------------------------
(?-imsx:                 group, but do not capture (case-sensitive)
                         (with ^ and $ matching normally) (with . not
                         matching \n) (matching whitespace and #
                         normally):
----------------------------------------------------------------------
  ^                        the beginning of the string
----------------------------------------------------------------------
  \+                       '+'
----------------------------------------------------------------------
)                        end of grouping
----------------------------------------------------------------------

更新: コメントの Mikko L が指摘したように、このコードをリファクタリング/変更する必要があります。おそらく想定どおりの動作をしますが、読みやすくすることをお勧めします。誰がそれを書いたとしても、後のメンテナであるあなたのことは明らかに気にかけませんでした。そうすることをお勧めします。次のように変更できます。

# look at the content of $_ (current line?)
if ( s/^\+// )
{
  # the line starts with a + sign,
  # which we remove!

  #do something
}
elsif ( m/^-/ )
{
  # the line starts witha - sign
  # we do NOT remove the - sign!

   #do another thing
}
于 2012-11-22T12:16:28.077 に答える
5

これらは正規表現であり、パターン マッチングと置換に使用されます。

あなたは概念を読むべきですが、あなたの質問に関しては:

s/^\+//

文字列がプラスで始まる場合、そのプラスを削除し ("s" は "代用" を意味します)、true を返します。

/^-/

文字列がマイナスで始まる場合は true。

于 2012-11-22T12:16:34.550 に答える
3

このコードは次と同等です

if ($_ =~ s/^\+//) {  # s/// modifies $_ by default
   #do something
}
elsif ($_ =~ m/^-/) {  # m// searches $_ by default
   #do another thing
}

s///およびm//は、正規表現の引用のような演算子です。それらについてはperlopで読むことができます。

于 2012-11-22T12:18:48.057 に答える
2

他の回答は、コードがどのように機能するかの概要を示していますが、その理由はあまりありません。このようなロジックを使用する理由の簡単な例を次に示します。

#!/usr/bin/env perl

use strict;
use warnings;

my $args = {};

for ( @ARGV ) {
  if ( s/^no// ) {
    $args->{$_} = 0;
  } else {
    $args->{$_} = 1;
  }
}

use Data::Dumper;
print Dumper $args;

次のようにスクリプトを呼び出すと

./test.pl hi nobye

あなたが得る

$VAR1 = {
          'hi' => 1,
          'bye' => 0
        };

キーは文字列ですが、 が前に付いている場合はno(問題のキーを取得するために) 削除し、代わりに値を に設定します0

OP の例はもう少し複雑ですが、同じロジックに従います。

  • キーがで始まる場合は、+それを削除して何かをしてください
  • キーが で始まる場合は、-それを削除せずに別のことをしてください
于 2012-11-22T15:34:32.933 に答える