如何将$ _的值更改为perl中grep中所需的值?

时间:2013-04-25 07:31:57

标签: perl grep

在此代码中,我想访问散列{IS-VAR}数组的每个元素的键@Cleared的值。当它进入循环内部时$_设置为$_->{'NAME'}

的值
if (grep {$_->{'NAME'} eq $entity_name} @Cleared)
{
  **$is_var = $_->{'IS-VAR'};**
  $var_flag = 1 if ($is_var =~ /^TRUE$/i);
}

有没有办法在循环中访问$_->{'IS-VAR'}的值,$_在此上下文中是@Cleared的元素?

@Cleared的结构如下:

@Cleared = [NAME => 'xxx',
            TYPE => 'yyy',
            IS-VAR => 'TRUE'];

2 个答案:

答案 0 :(得分:10)

您的代码存在的问题是您在grep语句中使用if。这会将grep的结果转换为标量(这将是找到的元素grep的数量)。因此,您实际上并不知道哪些元素匹配。

如果将其转换为for循环,您将能够访问匹配的每个元素;你的其余代码将逐字工作:

foreach (grep {$_->{'NAME'} eq $entity_name} @Cleared)
{
    $is_var = $_->{'IS-VAR'};
    $var_flag = 1 if ($is_var =~ /^TRUE$/i);
}

但是,如果您只想查找单个行是否匹配,则可以将其全部压缩为单个grep:

my $is_var = grep {
    $_->{'NAME'} eq $entity_name && $_->{'IS-VAR'} =~ /^TRUE$/i
} @Cleared;

现在$is_var包含匹配的元素数量。如果至少有一个匹配,则if ($is_var) {...}将为真。

如果您只需要知道是否存在至少一个匹配项,那么

grep不是最有效的方法。理想情况下,您应该在找到一个匹配后立即停止:

my $is_var;
foreach (@Cleared)
{
    if ($_->{'NAME'} eq $entity_name && $_->{'IS-VAR'} =~ /^TRUE$/i)
    {
        $is_var = 1;
        last;          #break out of the loop
    }
}

答案 1 :(得分:0)

你可以尝试更简单的循环:

for my $cleared (@Cleared) {
  if ($cleared->{NAME} eq $entity_name && $cleared->{IS_VAR} eq 'TRUE') {
    $var_flag = 1
   }
}