3

次の 4 つの部分で構成されるイメージ ファイル名があります。

  1. $Directory(画像が存在するディレクトリ)
  2. $Name(アートサイトの場合、これは絵画の名前参照番号です)
  3. $File(画像ファイル名から拡張子を引いたもの)
  4. $Extension(画像の拡張子)
$example 100020003000.png

それに応じて分解したい:

$dir=1000 $name=2000 $file=3000 $ext=.png

substr が着信を分割するのに最適なオプションであるかどうか疑問に思っていた$exampleので、検証/エラーチェック、$Name割り当てから詳細な名前を取得するなど、4 つの変数を使用して何かを行うことができます。この投稿を見つけました:

unpack は substr よりも高速ですか? だから、私の初心者の「石器」アプローチでは:

my $example = "100020003000.png";
my $dir = substr($example, 0,4);
my $name = substr($example, 5,4);
my $file = substr($example, 9,4);
my $ext = substr($example, 14,3); # will add the the  "." later #

では、アンパックを使用できますか、それともより効率的な別のアプローチを使用できますか?

また、何らかの理由でリソースの使用量が減らない限り、モジュールのロードは避けたいと思います。Mod は素晴らしいツールですが、ここでは必要ないと思います。

おそらく変数を配列/ハッシュにプッシュする必要があることはわかっていますが、私はここでは本当に初心者なので、その方法とそれらを引き出す方法についてさらに説明が必要です。

stackoverflow.com の皆さんに感謝します。

4

5 に答える 5

12

絶対:

my $example = "100020003000.png";
my ($dir, $name, $file, $ext) = unpack 'A4' x 4, $example;

print "$dir\t$name\t$file\t$ext\n";

出力:

1000 2000 3000 .png
于 2009-10-07T22:00:04.630 に答える
5

そのために正規表現を使用します。

my ($dir, $name, $file, $ext) = $path =~ m:(.*)/(.*)/(.*)\.(.*):;

または、特定の例に一致させるには:

my ($dir, $name, $file, $ext) = $example =~ m:^(\d{4})(\d{4})(\d{4})\.(.{3})$:;
于 2009-10-07T21:57:58.160 に答える
3

を使用するunpackのは良いことですが、要素はすべて同じ幅であるため、正規表現も非常に単純です。

my $example = "100020003000.png";
my ($dir, $name, $file, $ext) = $example =~ /(.{4})/g;
于 2009-10-07T22:22:29.863 に答える
1

解凍はしませんが、4文字のグループがあるため、キャプチャを使用して制限付き分割を使用できます。

my ($dir, $name, file, $ext) = grep length, split /(....)/, $filename, 4;

これはかなりわかりにくいので、おそらく使用しないでしょうが、分割でのキャプチャは見過ごされがちな能力です。

したがって、このコードの機能の説明は次のとおりです。

手順1.split括弧をキャプチャすると、パターンによってキャプチャされた値が出力ストリームに追加されます。ストリームには、フィールドと区切り文字が混在しています。

qw( a 1 b 2 c 3 ) == split /(\d)/, 'a1b2c3';

ステップ2.3splitつの引数を使用して、文字列が分割される回数を制限します。

qw( a b2c3 ) == split /\d/, 'a1b2c3', 2;

ステップ3.ここで、ほぼすべてに一致する区切り文字パターンを使用すると/(....)/、空の(長さ0)文字列の束が得られます。区切り文字をD文字でマークし、フィールドをF:でマークしました。

 ( '', 'a', '', '1', '', 'b', '', '2' ) == split /(.)/, 'a1b2';
   F    D   F    D   F    D   F    D

ステップ4.したがって、フィールドの数を3に制限すると、次のようになります。

 ( '', 'a', '', '1', 'b2' ) == split /(.)/, 'a1b2', 3;
   F    D   F    D   F  

ステップ5.すべてをまとめると、これを行うことができます(拡張機能を使用し.jpegて、拡張機能が4文字より長くなるようにしました)。

 ( '', 1000, '', 2000, '', 3000, '.jpeg' ) = split /(....)/, '100020003000.jpeg',4;
   F   D     F   D     F   D     F       

ステップ6.ステップ5はほぼ完璧です。必要なのは、null文字列を取り除くことだけで、問題ありません。

(1000、2000、3000、'.jpeg')= grepの長さ、分割/(....)/、 '100020003000.jpeg'、4;

このコードは機能し、興味深いものです。しかし、他のどのソリューションよりもコンパクトではありません。ベンチマークはしていませんが、速度やメモリ効率の賞を受賞した場合は非常に驚きます。

しかし、本当の問題は、それが実際のコードに適しているにはトリッキーすぎるということです。splitフィールドデータを破棄しながら、区切り文字(およびおそらく1つの最後のフィールド)をキャプチャするために使用するのはあまりにも奇妙です。また、壊れやすいです。1つのフィールドの長さが変わると、コードが壊れて書き直さなければなりません。

したがって、実際にはこれを行わないでください。

少なくとも、のあまり知られていない機能を探索する機会を提供しましたsplit

于 2009-10-08T18:44:46.753 に答える
0

正規表現ソリューションは、区切り記号を使用した柔軟なレイアウトに向けられていますが、どちらも固定レイアウトに考え方substrunpack偏らせます。

あなたが与えた例は固定レイアウトのように見えましたが、ディレクトリは通常、区切り文字でファイル名から区切られています (たとえば、POSIX スタイルのファイル システムのスラッシュ、MS-DOS のバックスラッシュなど)。したがって、実際には両方の場合があります。ディレクトリとファイル名(またはディレクトリ/名前/拡張子)を分割する正規表現ソリューションと、名前部分自体の固定長アプローチ。

于 2009-10-07T22:10:23.930 に答える