【问题标题】:Search for specific lines from a file从文件中搜索特定行
【发布时间】:2016-09-13 03:08:35
【问题描述】:

我有一个包含来自文本文件的数据的数组。

我想过滤数组并将一些信息复制到另一个数组。 grep 好像不行。

这就是我所拥有的

$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";
    }
}

文件.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

正则表达式应该取最后一两个文件夹,并将它们放入自己的数组中进行打印。

【问题讨论】:

标签: windows perl directory


【解决方案1】:

正则表达式可能对此非常挑剔。将路径拆分为组件然后根据需要计算多个组件要容易得多。并且有一个工具可以达到这个目的,核心模块File::Spec,正如xxfelixxx 在评论中提到的那样。

您可以使用它的splitdir 分解路径,并使用catdir 组合路径。

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 @path = splitdir $_;

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

say for @dirs;

我使用模块的功能接口,而对于繁重的工作,您需要它的面向对象的接口。将整个文件读入数组有其用途,但通常是逐行处理。列表操作可以更优雅地完成,但我是为了简单。

我想补充几个通用的cmets

  • 总是use strictuse warnings开始你的程序

  • 使用词法文件句柄,my $fh 而不是 FH

  • 了解(至少)十几个最常用的模块真的很有帮助。例如,在上面的代码中,我们甚至不必提及分隔符\

【讨论】:

  • 无需将整个文件复制到@lines。一个简单的while ( &lt;$fh&gt; ) 会更好。
  • @Borodin 无论如何——我打算保留他们的代码。但是,最好改变一些。谢谢。
  • 哇。非常感谢,我将不得不阅读它是如何工作的。
  • @cacartano 不客气 :)。是的,请阅读该模块——它非常简单。如果任何代码需要解释让我知道,我会补充。
【解决方案2】:

我无法写出完整的答案,因为我正在使用我的手机。无论如何,zdim 大部分都回答了你。但我的解决方案看起来像这样

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;

【讨论】:

    猜你喜欢
    • 2014-12-18
    • 2015-12-25
    • 1970-01-01
    • 2013-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-27
    相关资源
    最近更新 更多