1

簡単な質問:スクリプトのユーザーに、"[1 .. 5]"またはなどの任意の配列を入力できるようにしたい"[1, 2, 6, 9 .. 20]"。現在、私evalは与えられた文字列(明らかにあまり安全ではありません!)だけでperlcritic、レベル5の警告を出します。

私の現在のコード:

my $arr = eval $patternData{"arr"};
unless ($arr) {
     # fixes <arr> values like "(1 .. 5)"
     $arr  = undef;
     @$arr = eval $patternData{"arr"};
}

編集:多くの人が尋ねているように:これは「より良い」ものです。私は、強力な(表現力の点で)ソリューションと単純な(デバッグ、解析、入力の書き込みの点で)ソリューションの両方を探しています。また、絶対に範囲をサポートする必要があります(100エントリをはるかに超える配列は簡単に入力する必要があります)

そして-いつものように-私は自分のバージョンを含めるのを忘れました。5.8は必須です。私はvSphereAPIを使用していますが、これには5.8が必要です(私は~~とても恋しいです!)

This is perl, v5.8.8 built for MSWin32-x86-multi-thread
(with 50 registered patches, see perl -V for more detail)

Copyright 1987-2006, Larry Wall

Binary build 820 [274739] provided by ActiveState http://www.ActiveState.com
Built Jan 23 2007 15:57:46
4

2 に答える 2

4

現在の入力フォーマットとどの程度結びついていますか?

1つの解決策は、形式をJSONに「変更」し、JSON::XSを使用して入力を逆シリアル化することです。[1, 2, 3, 4]まだ有効な入力ですが、これでは許可されません[1, 2, 3, 4, 8 .. 10 ]

もちろん、すべての場合において、入力データが正しい構造を持っていることを検証する必要があります。

于 2012-09-25T07:46:02.850 に答える
2

配列で数値のみが許可されている場合は、このパターンを選択します(解析が簡単です)。

[1, 2, 3, 4]

[1, [2, 3]]さらに、ネストされた配列、たとえば、または末尾のコンマは存在しないと仮定します[1,]

次に、配列の区切り文字を削除します

my $line = <STDIN>;
$line =~ s/ ^\s*\[ | \]\s*$ //gx;

配列をPerl配列に分割します。私たちはどちらかを介してこれを行うことができますsplit

my @array = split /,\s*/, $line;

またはすべての数字を抽出することによって

my @array = ($line =~ /(\d+)(?:,\s*|$)/g);

このsplitソリューションでは、たとえば文字列を含めることもできます[1, two, 3]が、2番目のソリューションはより厳密です(したがって、おそらくより安全です)。

2番目のステップでは、範囲を解析できます。

@array = map {
   ($_ =~ /^(-?[\d.]+)\s*\.\.\s*(-?[\d.]+)/)
   ? ($1 .. $2)
   : $_
} @array;

データ構造がより複雑になる場合(繰り返し、引用)、Regexp::Grammarsを使用してパーサーを作成することを強くお勧めします。これにより、再帰構造やその他のほとんどすべてを簡単に解析できます。

于 2012-09-25T07:42:16.183 に答える