1

最初の列に数字と大文字で構成された製品コードのリストを含むcsvファイルがあり、 2番目の列には最初の列の製品の写真の名前用の空きスペースがあります。

ほとんどすべての写真を含むフォルダーもありますが、写真のコードは製品コードの部分文字列 (編集:プレフィックス) です。画像と商品の一致は 1 対多であるため、複数の商品が同じ画像を共有しています。例えば:

3234P3001 and 3234P3002 have the same picture 3234P30

csv ファイル内のコードのリストをスキャンするシェル スクリプトを作成する必要があります。名前がこのコードの部分文字列である画像がある場合は、その画像の名前を 2 列目に書き込みます

これは私の最初の大きなプロジェクトであり、データ操作の経験がありません。

写真の間の最大部分文字列を見つけることは、私の製品の写真です。

4

3 に答える 3

2

これはあなたが望むことをほとんど行います。

製品コードがproducts.csvというファイルに保存されていると仮定すると、以下のコードを「go」というファイルに保存すると、

chmod +x go
./go < products.csv

微調整が必​​要かも…

#!/usr/bin/perl

use strict;
use warnings;
use Data::Dumper;
use Cwd;

my $Debug=1;        # Set to 0 to turn off debug output
my $photosdir="/tmp";   # Or wherever your photos are

# Go to photos directory and load names of all JPEGs into array @photos
chdir $photosdir or die "Unable to chdir() to $photosdir\n";
my @photos=<*.jpg>;

# Debug - output photo filenames
print Dumper @photos if $Debug;

# Read product codes from our stdin
while(<>){
   chomp;
   my $product = $_ ;
   $product =~ s/;.*//;

   print "Finding photo for product: $product\n" if $Debug;

   # Run through all photo filenames and find longest match
   my $longestmatch=0;
   my $bestimage="<NONE>";

   foreach my $photo (@photos){
         # Strip extension off photo name
         $photo =~ s/\.jpg//;

         print "Assessing photo $photo\n" if $Debug;

         if($product =~ m/(^$photo)/ ){
            my $matchlength = length($&);
            if($matchlength > $longestmatch){
               print "Best match so far: $photo, ($matchlength characters)\n" if $Debug;
               $longestmatch = $matchlength;
               $bestimage = $photo . ".jpg";
            }
         }
   }
   print "$product,$bestimage\n";
}

実際には、ハッシュを使用すると、もう少しエレガントかつ高速に実行できます。最長の一致を見つけるまで何千枚もの写真をすべて見るのではなく、製品の最初の n 文字がハッシュに含まれているかどうかを確認してください。そうでない場合は、最初の n-1 文字、次に最初の n-2 文字を試してください。 、 このような。多数の製品や写真の場合は、はるかに高速に実行されるはずです。

#!/usr/bin/perl

use strict;
use warnings;
use Data::Dumper;
use Cwd;

my $Debug=1;        # Set to 0 to turn off debug output
my $photosdir="/tmp";   # Or wherever your photos are

# Go to photos directory and load names of all JPEGs into array @filenames
chdir $photosdir or die "Unable to chdir() to $photosdir\n";
my @filenames=<*.jpg>;

# Now create hash of photonames without ".jpg" extension
my %photos;
for my $photo (@filenames){
   $photo =~ s/\.jpg//;
   # So if there was a file "xyz.jpg", $photos{"xyz"} will be defined
   $photos{$photo}=1;
}

# Debug - output photo filenames
print Dumper \%photos if $Debug;

# Read product codes from our stdin
while(<>){
   chomp;   # remove end of line
   my ($product,$field2,$field3) = split ";";

   print "Finding photo for product: $product\n" if $Debug;

   my $bestimage="<NONE>";  # Preset and overwrite if better one found

   # Keep removing last character of product till it matches a photo
   for(my $i=length($product);$i;$i--){
      my $short = substr($product,0,$i);
      print "Trying $short\n" if $Debug;
      if(defined($photos{$short})){
         $bestimage = $short . ".jpg";
         last;
      }
   }
   print "$product;$bestimage;$field3\n";
}
于 2013-10-29T23:09:24.517 に答える