2015-06-26 120 views
1

我有一个文件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; 
    } 
} 

这将打印用户输入应用程序的名称,并没有别的。任何帮助将不胜感激!

+1

不要忘记['chomp'](http://perldoc.perl.org/functions/chomp.html)你的'$ app'换行符。 –

+0

啊,是的,一个非常愚蠢的错误 - 感谢吨指出来! –

回答

2

有与您的程序

  • 两个主要问题的$app变量包含在最后一个换行符回车键,你按下当你键入它。这将阻止模式匹配,因此您需要使用chomp将其删除。这同样适用于线从文件中读取

  • while语句中的<$fh>读取文件一行到默认变量$_,然后$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"; 
    } 
} 
+0

这很完美。谢谢!我无法相信我错过了像其他线路一样愚蠢的错误。 非常感谢! –

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); 
+0

非常感谢。这非常有帮助 –

0

你在你的循环访问<$fh>两次。这将只会解释每隔一行。您可能要在循环的顶部更改为类似这样:

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

,并在程序的顶部取下my $line ...

而且,你可能要考虑你大嚼输入线,这样你就不必去想尾部的换行符:

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

你的正则表达式也有点冒险。您可能希望将其绑定到搜索空间的开始和结尾并转义字面点。您可能还希望$app被解释为字符串而不是正则表达式,可以使用\Q...\E来包装它。另外,除非你的文件格式在等号附近指定了单个空格,否则我会试图让这些灵活性为零或多次出现。另外,如果你不打算使用较早的捕捉,我会说不要做,所以:

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

(可能有人会说,你应该使用\A\z而不是^$这样的选择。就留给读者做练习)

+0

非常感谢。 Twas对我来说真的很愚蠢,要两次访问这个文件句柄,并且忘记了后面的换行符!至于正则表达式,是的 - 我现在明白,我的确是个冒险家。 =符号周围的单个空格被指定,但是这对于我的下一个代码来说是非常好的反馈。 非常感谢! –

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; 

,然后请发送您的响应。

+0

你是硬编码COMP,这可能是任何东西。 –

+0

我认为应用程序名称为COMP – velz

+0

我知道你在做什么,我认为这是一个很好的方法 - 但硬编码不适合我,因为我有大量不是“COMP”的应用程序名称,也是。因此,我必须将其作为用户的输入。 谢谢你的帮助! –