簡體   English   中英

如何從Perl數組中提取出我想要的元素?

[英]How can I extract just the elements I want from a Perl array?

嘿,我想知道如何讓這段代碼工作。 基本上我想保留$filename的行,只要它們在路徑中包含$user

        open STDERR, ">/dev/null";
        $filename=`find -H /home | grep $file`;
        @filenames = split(/\n/, $filename);
        for $i (@filenames) {
            if ($i =~ m/$user/) {
                #keep results
            } else {
                delete  $i; # does not work.    
            }
        }
        $filename = join ("\n", @filenames);
        close STDERR;

我知道你可以刪除像delete $array[index]但我沒有這種循環的索引,我知道。

您可以用以下代碼替換循環:

@filenames = grep /$user/, @filenames;

當你使用foreach循環時,沒有辦法做到這一點。 但是沒關系。 正確的做法是使用File :: Find來完成您的任務。

use File::Find 'find';

...

my @files;
my $wanted = sub {
    return unless /\Q$file/ && /\Q$user/;
    push @files, $_;
};

find({ wanted => $wanted, no_chdir => 1 }, '/home');

不要忘記使用\\Q轉義變量以用於正則表達式。

順便說一句,將STDERR重定向到/dev/null更好地寫為

{
    local *STDERR;
    open STDERR, '>', '/dev/null';
    ...
}

它在退出塊后恢復文件句柄。

如果你有一個支持-pathfind ,那么讓它為你做的工作, 例如

#! /usr/bin/perl

use warnings;
use strict;

my $user = "gbacon";
my $file = "bash";

my $path = join " -a " => map "-path '*$_*'", $user, $file;
chomp(my @filenames = `find -H /home $path 2>/dev/null`);

print map "$_\n", @filenames;

注意列表上下文中的反引號如何從命令的輸出中返回一個行列表(包括它們的終結符,上面用chomp刪除)。 這樣可以節省您自己split

輸出:

/home/gbacon/.bash_history
/home/gbacon/.bashrc
/home/gbacon/.bash_logout

如果要從數組中刪除項目,請使用多才多藝的splice功能。

my @foo = qw( a b c d e f );

splice( @foo, 3, 1 ); # Remove element at index 3.

您可以使用splice各種其他操作。 有關詳細信息,請參閱perldoc


至於codeholic暗示,在遍歷它與你永遠不應該修改陣列for循環。 如果要在迭代時修改數組,請改用while循環。

這樣做的原因是, for在parens中計算表達式一次,並將結果列表中的每個項目映射到別名。 如果數組發生變化,指針就會搞砸,隨之而來的是混亂。

A while每次循環都會評估條件,因此您不會遇到指向不存在的值的問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM