Perl - 生成唯一标识符

时间:2012-10-08 19:44:51

标签: arrays perl contains

首先,我必须承认我是Perl的新手,所以对于某些人来说,我的问题可能看起来很糟糕,我很抱歉。我目前正在使用用于Perl的VMWare SDK,我仍然坚持上传功能。我想做的是为每个VMDK生成一个唯一的标识符(例如我添加到VM的硬盘)。基本上,用户提供硬盘应作为脚本的参数。

但是,如果用户选择已经采用的名称,则会出现问题。我想过很多解决方案,比如添加时间戳(这将是独一无二的),但我想要更优雅的东西。那么,让我们考虑一下:

@vmdks :列出虚拟机上已有的所有硬盘

$ filename :用户想要提供给VMDK的名称,一旦它在VM上

$ target :硬盘实际上具有的名称。

我想要像filename-00X这样的东西,其中X是出现的。因此,例如,如果有人试图添加名为“FOO”的硬盘,当一个已存在时,它将被重命名为“FOO-001”。请注意,用户只能输入带有字母数字字符的磁盘名称,因此他不能将硬盘命名为“FOO-001”,这样可以避免冲突。

因为我不太了解Perl,所以我决定用伪代码编写它,希望你不介意:

IF $filename IS IN @vmdks
   # So here we have a conflict

   IF $filename-X IS IN @vmdks  
      # X should be a 3-digit number, like 001, 002, 666, etc.
      INDEX := X
      INDEX++
      $target = $filename-INDEX
   ELSE
      $target = $filename-001
   ENDIF
ELSE
   $target = $filename 
ENDIF

我想我可以通过以下方式轻松完成第一个条件:

if(grep{$_ eq $filename} @vmdks) ...

但第二个......我真的被卡住了:/我怎么能匹配$ filename-index,然后检索后者呢?

非常感谢,我希望我足够清楚

2 个答案:

答案 0 :(得分:0)

您可以将所有候选人的子阵列视为:

my @tmp = grep(/^$filename-\d+/, @vmdks);

@tmp的最后一个元素将是$filename的最新索引文件名

答案 1 :(得分:0)

您也可以使用smart-match operator进行匹配。我已经在Perl中完成了伪代码,只需稍微调整一下你的算法。

请注意有多种方法可以做到这一点。您还可以使用哈希进行查找。这将更快丢失,但消耗更多的内存。这取决于任务,这是最好的选择。

#!/usr/bin/perl
use strict; use warnings;
use feature qw(say);

my @vmdks = qw( foo bar dilbert dilbert-001 );

sub test_filename {
  my ($filename) = @_;

  # abort if the filename is not alphanumeric
  return if $filename =~ /\W/;

  # check if the filename is in our list
  if ($filename ~~ @vmdks) {
    my $i = 1; # counter, starting at 1
    # check if the extended filename is in the list
    while ( sprintf('%s-%03d', $filename, $i) ~~ @vmdks ) {
      $i++; # increment
    }
    # assign the new filename
    $filename = sprintf('%s-%03d', $filename, $i);
  }

  return $filename;
}

# test ist
for (qw ( phb dilbert foo foo bar dogbert bar foo 1234 123) ) {
  say test_filename($_);
}