2015-06-26 2 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) новую строку с вашего' $ приложения'. –

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

вы hardcoding COMP, Это может быть что угодно. –

+0

Я воспринял имя приложения как COMP – velz

+0

Я получаю то, что вы делаете, и я думаю, что это хороший подход, но hardcoding не сделал бы для меня, поскольку у меня есть большое количество имен приложений, которые не являются «COMP», с, тоже. Следовательно, мне нужно принять это как вклад от пользователя. Благодарим за помощь! –

Смежные вопросы