在文件中搜索模式

时间:2015-06-26 04:22:09

标签: regex perl file-io

我有一个文件eg.txt,其中包含以下内容:

....text...
....text...
COMP1 = ../../path1/path2/path3
COMP2 = ../../path4/path5/path6

等等,对于大量的应用程序名称(“COMP”)。对于用户指定的应用程序,我需要获取路径 - 包括第二个斜杠后的内容。

这是我一直在尝试的代码:

use strict;
use warnings;

my $line = "";
my $app  = "";

print "Enter the app";
$app = <STDIN>;
print $app;

open my $fh, '<', "eg.txt" or die "Cannot open $!";

while (<$fh>) {
    $line = <$fh>;
    if ( $line && $line =~ /($app)( = )(..\/)(..)(.*)/ ) {
        print $5;
    }
}

这将打印用户输入应用程序的名称,而不执行任何其他操作。任何帮助将不胜感激!

4 个答案:

答案 0 :(得分:2)

您的计划有两个主要问题

  • $app变量在您输入时按下的回车键的末尾包含换行符。这将阻止模式匹配,因此您需要使用chomp删除它。这同样适用于从文件中读取的行

  • <$fh>语句中的while会将文件中的一行读入默认变量$_,然后$line = <$fh>读取另一行,因此您忽略来自文件的备用行

以下是我认为应该可以使用的程序版本,但我目前无法对其进行测试。我完全放弃了你的$line变量,希望这不会让你感到困惑。 $_是模式匹配的默认变量,因此不会在任何地方明确提及

use strict;
use warnings;

print "Enter the app: ";
my $app = <STDIN>;
chomp $app;

open my $fh, '<', 'eg.txt' or die "Cannot open: $!";

while ( <$fh> ) {
    if ( /$app\s*=\s*(.+)/ ) {
        my $path = $1;
        $path =~ s/.*\.\.//;
        print $path, "\n";
    }
}

答案 1 :(得分:1)

输入在正则表达式中不匹配,因为换行符随之而来,所以最好使用chomp来修剪它们。在while循环中,你取代了两倍的文件句柄,我不知道为什么。因此,在更正后,这应该有效:

use strict;
use warnings;
my $line = "";
my $app = "";

print "Enter the app";
chomp($app = <STDIN>);
print "$app: ";

open my $fh, '<', "eg.txt" or die "Cannot open $!";

while($line = <$fh>)
{
    chomp $line;
    if($line && $line =~ /($app)( = )(..\/)(..)(.*)/)  
    {
        print "$5 \n";
    }
}
close($fh);

答案 2 :(得分:0)

您在循环中访问<$fh>两次。这将具有仅解释所有其他行的效果。您可能希望将循环顶部更改为以下内容:

while (defined(my $line = <$fh>)) {

并删除程序顶部的my $line ...

此外,您可能需要考虑选择输入行,这样您就不必考虑尾随换行符:

while (defined(my $line = <$fh>)) {
    chomp $line;

你的正则表达式也有点冒险。您可能希望将其绑定到搜索空间的开头和结尾,并转义字面点。您可能还希望将$app解释为字符串而不是正则表达式,这可以通过使用\Q...\E包装来完成。除非你的文件格式指定了equals周围的单个空格,否则我很想将这些空间灵活地设置为零或更多。此外,如果你不打算使用早期的捕获,我会说不要这样做,所以:

if ($line && $line =~ /^\Q$app\E *= *\.\.\/\.\.(.*)$/)
{
    print $1;

(有些人可能会说你应该使用\A\z而不是^$。这个选择留给了读者。)

答案 3 :(得分:0)

试试这段代码:

use strict;
use warnings;
my $line = "";
my $app = "";

print "Enter the app";
$app = <STDIN>;
print $app;
open my $fh, '<', "eg.txt" or die "Cannot open $!";
my @line = <$fh>;
my @fetch = map { /COMP\d+\s\=\s(\..\/\..\/.*)/g  } @line ;
$, = "\n";
print @fetch;

然后请发送您的回复。