2013-11-12 5 views
2

Я являюсь абсолютным новичком в perl, и я пытаюсь извлечь строки текста между двумя строками на разных строках, но безуспешно. Похоже, я что-то пропустил в своем коде. Код должен распечатывать имя файла и найденные строки. У вас есть идея, где может быть проблема? Большое спасибо за вашу помощь или совет. Вот пример:Как извлечь строки между двумя строками

***************** 
example: 
START 
new line 1 
new line 2 
new line 3 
END 
***************** 

и мой сценарий:

use strict; 
use warnings; 

my $command0 = ""; 
opendir (DIR, "C:/Users/input/") or die "$!"; 
my @files = readdir DIR; 
close DIR; 
splice (@files,0,2); 

open(MYOUTFILE, ">>output/output.txt"); 
foreach my $file (@files) { 
    open (CHECKBOOK, "input/$file")|| die "$!"; 
    while ($record = <CHECKBOOK>) { 
     if (/\bstart\..\/bend\b/) { 
      print MYOUTFILE "$file;$_\n"; 
     } 
    } 
    close(CHECKBOOK); 
    $command0 = ""; 
} 
close(MYOUTFILE); 

ответ

0

Если вы совпадающей строки многострочного, что вам может понадобиться, чтобы сообщить об этом регулярное выражение:

if (/\bstart\..\/bend\b/s) { 

Обратите внимание на s после регулярного выражения.

Perldoc говорит:

  • сек

Treat строка в одной строке. То есть, измените "." чтобы соответствовать любому знаку , даже новой строке, которая обычно не соответствует .

+0

Я думаю, что вещь с '..' в середине должен быть флип-флоп, то есть'/\ bstart \ b/../\ bend \ b/'. – TLP

+0

Почему вы думаете, что он соответствует многострочной строке? Он явно пытается использовать флип-флоп-оператора. –

4

Я полагаю, что вы пытаетесь использовать флип-флоп здесь, которые могли бы хорошо работать для ввода, но вы написали его неправильно:

if (/\bstart\..\/bend\b/) { 

триггеру (диапазон оператор) использует два оператора, разделенных либо .., либо .... То, что вы хотите, два регулярных выражений вместе с ..:

if (/\bSTART\b/ .. /\bEND\b/) 

Конечно, вы также хотите, чтобы соответствовать случаю (верхнему), или использовать модификатор /i игнорировать регистр. Возможно, вы даже хотите использовать начало якоря ^ только матч в начале строки, например:

if (/^START\b/ .. /^END\b/) 

Вы также должны знать, что вся ваша программа может быть заменены однострочником, такие как

perl -ne 'print if /^START\b/ .. /^END\b/' input/* 

Увы, это работает только для Linux. Оболочка CMD в Windows, не шарик, так что вы должны сделать это вручную:

perl -ne "BEGIN { @ARGV = map glob, @ARGV }; print if /^START\b/ .. /^END\b/" input/* 

Если вы испытываете проблемы с печатью всего файла, независимо от того, что вы делаете, я думаю, что проблема заключается в входном файл. Так найдите время, чтобы изучить его и убедиться, что это то, что вы думаете, это, например:

perl -MData::Dumper -e"$Data::Dumper::Useqq = 1; print Dumper $_;" file.txt 
+0

Благодарим за помощь. Я внес изменения в соответствии с вашими предложениями, но каждый раз, когда я запускаю скрипт, он выводит весь файл вместо строк только между START и END.Он работает только в том случае, если строки START и END являются границами всего текста в файле, если у меня что-то есть до START, и после END он печатает весь файл. Любая идея почему? – user2983070

+0

Ну, вы делаете '$ record = ', а затем никогда не используете '$ record', что означает, что у вас много ошибок, и строки не должны печататься. Что касается того, почему все строки печатаются, я не знаю. Кажется, вы читаете файл в одной строке. – TLP

+0

вы правы с $ record. Я изменил его на: if ($ record = ~/\ start \ b/../^ end \ b /) { $ command0 = $ record; $ found = 1; } if ($ found == 1) { $ found = 0; } .... но все же он печатает все :( – user2983070

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