2015-09-24 2 views
0

Я пытаюсь разобрать некоторые исходные файлы и застрял в этой проблеме. Я ищу, чтобы соответствовать определенной строке, которая имеет «» и «>>>» в ней, и я пытаюсь удалить все символы новой строки, начиная с того момента, когда она найдет указанные символы до тех пор, пока не встретит первый «;» символ. Любая помощь будет высоко ценится.Perl удалять символы новой строки из совпадающей строки

Это то, что я пытаюсь сделать:

Вход:

... lines of code 
func1 <<< abc, xyz >>> (str1, 
         str2, 
         str3); 
... lines of code 

Выход:

... lines of code 
func1 <<< abc, xyz >>> (str1, str2, str3); 
... lines of code 

Переменные func1, азбука, хуг, str1, str2, str3 может все варьироваться.

Заранее благодарен.

EDIT:

Это то, что я пытался и до сих пор он печатает только по той же схеме, что и вход.

while (<$fh>) { 
    if (/\<\<\<.*\>\>\>/) { 
    while ($_ !~ /\)\s*\;/) { 
      chomp $_; 
      $_ = <$fh>; 
    } 
    print $_; 
    } 
} 

EDIT 2:

Проблема была решена. Посмотри ответы.

+1

Если строка содержит '<<< ... > >>', то 'chomp', и сростить следующая строка. Прополощите, повторите, пока не найдете ';' в конце строки. Готово. – TLP

+0

@TLP: Я тоже попытался объединиться. Но все равно это не сработает. –

+0

Вы не являетесь конкатенацией в этом коде. – TLP

ответ

-1

Хорошо, я понял, что делаю неправильно. Я пытался сделать это на месте. Опять его неэффективно, я думаю, но он работает.

EDIT: Решено не менять оригинал. Измененный код с полезными входами от @TLP

open my $fh, "<", $ARGV[0] or die "$!"; 
open my $out, ">", "output.out" or die "$!"; 
while (<$fh>) 
{ 
    if (/\<\<\<.*\>\>\>/) 
    { 
     while (1) 
     { 
      if (/\)\s*\;/) { s/\s//g; last; } 
      else { s/\s//g; 
       $_ .= <$fh>; } 
     } 
    } 
    print $out $_."\n"; 
} 

close $out; 
close $fh; 
+0

Возможно, вас заинтересует переключатель '-i', который сделает для вас редактирование на месте. Хотя мое личное предпочтение заключается в том, чтобы не изменять оригиналы, а вместо этого делать 'perl foo.pl input.txt> output.txt'. Кроме того, 1) '\ s' включает' \ n', поэтому нет необходимости в двух подстановках. 2) Вы можете пропустить один из операторов 'print', если вы переместите его вне блока' if' или используйте блок 'continue'. Использование '. =' Часто предпочтительнее использования двух операторов. И вам не нужно избегать всех этих символов в ваших регулярных выражениях. Для этого нужно избегать только ')', и вам действительно не нужно его использовать, поскольку '/; \ s * $ /' – TLP

+1

@TLP: Спасибо за входные данные. Ценить это. –

3
my @long, $end; 
while (<>) {        # read a line 
    if (/<<<.*>>>/ .. ($end = /;/)) {  # if needs joining, 
    s/^\s+|\s+$//g;      # trim it 
    push @long, $_;      # add to list 
    print join(' ', @long) . "\n" if $end; # paste and print if at end 
    } else {         # if doesn't need joining, 
    print;         # just print without changes 
    } 
} 
0

Это должно работать:

perl -npe 'if (/<<<.*?>>>/../;/) { chomp unless /;/ }' filename 

Вот что он делает:

  1. перебрать все строки в файле (опция -n)
  2. Соедините все строки между (и в том числе) <<<.*?>>> и ; и удалите символы перевода. Это не делается для строки, содержащей ;.
  3. печати все линии (опция -p)
0

Предполагая, что мы говорим о сжатии, которое содержит <<< и, насколько ;:

#!/usr/bin/perl 
use strict; 
use warnings; 

while (<DATA>) { 
    if (m/<<</ .. m/\);$/) { 
     s/\s+/ /g; 
     s/;\s*$/;\n/g; 
    } 
    print; 
} 

__DATA__ 
... lines of code 
func1 <<< abc, xyz >>> (str1, 
         str2, 
         str3); 
... lines of code 
  • Мы используем оператор диапазона чтобы определить, находимся ли мы между <<< и \);$
  • Если мы находимся, мы заменяем пробелы и переводы строк пробелами.
  • И мы тогда должны снова вставить роспускной перевод строки после ;

Воспроизводит:

... lines of code 
func1 <<< abc, xyz >>> (str1, str2, str3); 
... lines of code 
Смежные вопросы