1

次の文字列があります。

$str = "list
    XYZ

    status1    : YES
    value1     : 100
    status2      : NO
    value2     : 200
Thats all";       

この文字列を入力として受け取り、たとえばキーstatus1としてハッシュを返す関数を使用して、それをハッシュに変換したいと思います。YES

その方法は?
そして、返されたハッシュを参照する方法は?

4

4 に答える 4

14

いつものように、それを行うには複数の方法があります。5人来ました。

純粋な正規表現 (YEAH!)

これが一番かっこいいと思います。正規表現は、ハッシュを初期化したいリストとまったく同じすべてのキャプチャのリストを返します。

my %regex = $str =~ /(\S+)\s*:\s*(\S+)/g;

反復

これは、ほとんどのプログラマーにとって最も簡単な方法だと思います。

my @lines       = split /\R/ => $str;
my %iterative   = ();
for (@lines) {
    next unless /(\S+)\s*:\s*(\S+)/;
    $iterative{$1} = $2;
}

ここで説明することは何もありません。最初splitに文字列を行単位で処理し、次にそれらを反復処理して、のように見えない行を除外しますfoo : bar。終わり。

リスト処理

すべてを大きなリスト式として書くのは少しハックに感じますが、何かを表現する方法をもっと学ぶには興味深いかもしれません。

my %list =  map     { /(\S+)\s*:\s*(\S+)/ and $1 => $2 }
            grep    { /:/ }
            split   /\R/ => $str;

右から左に読む: 上記の例のように、文字列を行単位で分割することから始めます。grep行をフィルタリング:し、最終的なマップで、キーと値を使用して、一致する行文字列を長さ 2 のリストに変換します。

リスト削減

List::Utilreduce関数の重要な使用例は非常にまれです。上記のリスト アプローチに基づいて、ハッシュ参照を返すものを次に示します。

my $reduced = reduce {
    $a = { $a =~ /(\S+)\s*:\s*(\S+)/ } unless ref $a;
    $a->{$1} = $2 if $b =~ /(\S+)\s*:\s*(\S+)/;
    return $a;
} grep { /:/ } split /\R/ => $str;

ステートマシン

これは、空白の分離のみに正規表現を使用した面白いものです。状態を追跡する必要があります。

# preparations
my $state   = 'idle';
my $buffer  = undef;
my %state   = ();
my @words   = split /\s+/ => $str;

# loop over words
for my $word (@words) {

    # last word was a key
    if ($state eq 'idle' and $word eq ':') {
        $state = 'got_key';
    }

    # this is a value for the key in buffer
    elsif ($state eq 'got_key') {
        $state{$buffer} = $word;
        $state          = 'idle';
        $buffer         = undef;
    }

    # remember this word
    else {
        $buffer = $word;
    }
}
于 2012-10-22T10:11:04.217 に答える
2

楽しみのために(memoweのいずれかを使用することをお勧めします)、YAMLを(ab)使用するものを次に示します。

#!/usr/bin/env perl

use strict;
use warnings;

use YAML;

my $str = "list
    XYZ

    status1    : YES
    value1     : 100
    status2      : NO
    value2     : 200
Thats all";

$str = join "\n", grep { /:/ } split "\n", $str;
my $hash = Load "$str\n";
于 2012-10-22T18:29:01.313 に答える
1
#!/usr/bin/perl
use warnings;

$\="\n";

sub convStr {
        my $str = $_[0];
        my %h1=();
        while ($str =~m/(\w+)\s+:\s+(\w+)/g) {
                $h1{$1} =$2;
        }
        return \%h1;
}

my $str = "list
    XYZ

    status1    : YES
    value1     : 100
    status2      : NO
    value2     : 200
Thats all";

my $href=convStr($str);

foreach (keys(%$href)) {
        print $_ , "=>", $href->{$_};
}

これを実行すると、次のようになります。

status2=>NO
value1=>100
status1=>YES
value2=>200
于 2012-10-22T09:04:44.340 に答える
0
  my %hhash;
  my @lines = split /\s+\n/, $str;
          foreach (@lines)
          {
            $_=~s/^\s+//g;
            if(/:/)
            {
            $key=(split(/:/))[0];
            $value=(split(/:/))[1];
            $hhash{$key}=$value;
            }
          }
于 2012-10-22T09:27:00.027 に答える