簡體   English   中英

如何處理不包含模式的文件?

[英]How to handle files that do not contain a pattern?

我的Perl程序需要幫助。 這個想法是從命令行傳遞模式和文件列表。 如果文件名與模式匹配,則打印文件名。 然后,如果文件名不匹配,則應在文件的文本中查找模式的實例並打印文件名:包含出現的文本的第一行

但是,如果用戶在開頭添加-i選項,則會出現相反的情況。 如果文件名不匹配,請打印。 然后打印任何文本中不包含任何模式實例的文件。

這是我在奮斗的最后一部分,我不確定如何獲取文本中沒有模式的文件。 例如在我的代碼中

#!/usr/bin/perl -w
die("\n Usage: find.pl [-i] <perlRegexPattern> <listOfFiles>\n\n") if(@ARGV<2);

my (@array,$pattern,@filesmatch,@files);
#I can separate files based on name match
($pattern,@array) = ($ARGV[0] eq "-i") ? (@ARGV[1 .. $#ARGV]) : (@ARGV);

foreach(@array){
    ($_ =~ m/.*\/?$pattern/) ? (push @filesmatch,$_) : (push @files, $_);
}
#and I can get files that contain a pattern match in their text
if($ARGV[0] ne "-i"){
    for my $matches(@filesmatch){ #remove path print just file name
        $matches =~s/.*\///;      #/
        print "$matches\n";
    }
    for my $file(@files){
        open(FILE,'<',$file) or die("\nCould not open file $file\n\n");
        while(my $line = <FILE>){
            if($line =~ m/$pattern/){
                $file =~ s/.*\///; #/ remove path print just file name
                print "$file: $line";
                next;
            }
        }
    }
}
#however I'm not sure how to say this file dosen't have any matches so print it
else{
    for my $matches(@files){ #remove path print just file name
        $matches =~ s/.*\///;
        print "$matches\n";
    }
    for my $file(@filesmatch){
        open(FILE,'<',$file) or die("\nCould not open file $file\n\n");;
        while(my $line = <FILE>){...

我不確定是否可以使用grep之類的方法來執行此操作,但是我在使用Perl的grep時遇到了困難。

為了根據文件的內容決定是否打印文件,您必須首先讀取文件。 根據您的標准-短語不存在-您必須檢查整個文件。

一種標准方法是使用單獨的變量(“標志”)記錄條件,然后返回打印

my $has_match;
while (<$fh>) {
   if (/$pattern/) {
       $has_match = 1;
       last;
   }
}
if (not $has_match) {
    seek $fh, 0, 0;     # rewind to the beginning
    print while <$fh>;
}

可以通過首先將文件讀入變量並使用標簽來簡化此操作(另請參見perlsyn

FILE: foreach my $file (@filesmatch) {
    open my $fh, '<', $file or die "Can't open $file: $!";
    my @lines = <$fh>;

    for (@lines) {
        next FILE if /$pattern/;
    }   
    print for @lines;
}

請注意,在循環的中間跳過迭代並不是最干凈的方法,因為必須牢記循環的其余部分可能不會運行。

每個文件都會被首先讀取,因此我們不會讀取兩次,但是如果其中任何一個文件可能很大,都不要這樣做。


如果有任何命令行處理,最好使用模塊。 Getopt :: Long很不錯。

use Getopt::Long;

my ($inverse, $pattern);    
GetOptions('inverse|i' => \$inverse, 'pattern=s' => \$pattern)
    or usage(), exit;    
usage(), exit if not $pattern or not @ARGV;

sub usage { say STDERR "Usage: $0 ... " }

progname [-i] --patern PATTERN files調用程序。 該模塊提供了很多功能,請參閱文檔。 例如,在這種情況下,您也可以只使用-p PATTERN

GetOptions解析命令行時,已提交的選項已從@ARGV中刪除,其中剩下的是文件名。 並且您可以使用$inverse變量很好地進行決策。


請有use warnings; 不是 -w )並use strict; 在每個程序的頂部。

暫無
暫無

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

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