Search for specific lines from a file

落爺英雄遲暮 提交于 2019-12-12 04:22:07

问题


I have an array that contains the data from a text file.

I want to filter the array and copy some information to another array. grep seems to not work.

Here's what I have

$file = 'files.txt';

open (FH, "< $file") or die "Can't open $file for read: $!";
@lines = <FH>;
close FH or die "Cannot close $file: $!";

chomp(@lines);

foreach $y (@lines){

    if ( $y =~ /(?:[^\\]*\\|^)[^\\]*$/g ) {
        print $1, pos $y, "\n";
    }
}

files.txt

public_html
Trainings and Events
General Office\Resources
General Office\Travel
General Office\Office Opperations\Contacts
General Office\Office Opperations\Coordinator Operations
public_html\Accordion\dependencies\.svn\tmp\prop-base
public_html\Accordion\dependencies\.svn\tmp\props
public_html\Accordion\dependencies\.svn\tmp\text-base

The regular expression should take the last one or two folders and put them into their own array for printing.


回答1:


A regex can get very picky for this. It is far easier to split the path into components and then count off as many as you need. And there is a tool that fits your exact purpose, the core module File::Spec, as mentioned by xxfelixxx in a comment.

You can use its splitdir to break up the path, and catdir to compose one.

use warnings 'all';
use strict;
use feature 'say';

use File::Spec::Functions qw(splitdir catdir);

my $file = 'files.txt';    
open my $fh, '<', $file or die "Can't open $file: $!";

my @dirs;    
while (<$fh>) {
    next if /^\s*$/;  # skip empty lines
    chomp;

    my @all_dir = splitdir $_;

    push @dirs, (@all_dir >= 2 ? catdir @all_dir[-2,-1] : @all_dir);
}
close $fh;

say for @dirs;

I use the module's functional interface while for heavier work you want its object oriented one. Reading the whole file into an array has its uses but in general process line by line. The list manipulations can be done more elegantly but I went for simplicity.

I'd like to add a few general comments

  • Always start your programs with use strict and use warnings

  • Use lexical filehandles, my $fh instead of FH

  • Being aware of (at least) a dozen-or-two of most used modules is really helpful. For example, in the above code we never had to even mention the separator \.




回答2:


I can't write a full answer because I'm using my phone. In any case zdim has mostly answered you. But my solution would look like this

use strict;
use warnings 'all';
use feature 'say';

use File::Spec::Functions qw/ splitdir catdir /;

my $file = 'files.txt';

open my $fh, '<', $file or die qq{Unable to open "$file" for input: $!};

my @results;

while ( <$fh> ) {
    next unless /\S/;
    chomp;
    my @path = splitdir($_);
    shift @path while @path > 2;
    push @results, catdir @path;
}

print "$_\n" for @results;


来源:https://stackoverflow.com/questions/39461658/search-for-specific-lines-from-a-file

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!