كيف يمكنني استخراج خطوط بين اثنين من خط المحددات في بيرل?

StackOverflow https://stackoverflow.com/questions/1212799

سؤال

لدي ASCII ملف السجل مع بعض المحتوى أود أن استخراج.أنا لم أخذ الوقت لتعلم بيرل بشكل صحيح ولكن أظن أن هذا هو وسيلة جيدة من أجل هذه المهمة.

الملف منظم مثل هذا:

... 
... some garbage 
... 
... garbage START
what i want is 
on different
lines 
END 
... 
... more garbage ...
next one START 
more stuff I want, again
spread 
through 
multiple lines 
END 
...
more garbage

لذا أنا أبحث عن طريقة استخراج خطوط بين كل START و END محدد السلاسل.كيف يمكن أن أفعل هذا ؟

حتى الآن, لقد وجدت فقط بعض الأمثلة على كيفية طباعة خط مع START سلسلة أو وثائق أخرى العناصر التي هي ذات الصلة إلى حد ما مع ما كنت أبحث عنه.

هل كانت مفيدة؟

المحلول

وأنت تريد المشغل قلاب (المعروف باسم مشغل المدى) ..

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

while (<>) {
  if (/START/../END/) {
    next if /START/ || /END/;
    print;
  }
}

واستبدال الدعوة إلى print مع كل ما كنت فعلا تريد أن تفعل (على سبيل المثال، ودفع خط في صفيف، وتحريرها، وشكل ذلك، أيا كان). أنا next جي الماضي الخطوط التي لديها START أو END في الواقع، ولكن قد لا تحتاج ذلك السلوك. انظر هذه المقالة لمناقشة هذا المشغل وغيرها مفيدة بيرل المتغيرات الخاصة.

نصائح أخرى

perlfaq6 الصورة الإجابة على <لأ href = "HTTP: //faq.perl كافيه / perlfaq6.html # How_can_I_pull_out_l "يختلط =" noreferrer "> كيف يمكنني سحب خطوط بين نمطين التي هي نفسها على خطوط مختلفة؟


ويمكنك استخدام .. مشغل بيرل غريبة نوعا ما (وثقت في perlop):

perl -ne 'print if /START/ .. /END/' file1 file2 ...

إذا كنت تريد خطوط النص وليس، يمكنك استخدام

perl -0777 -ne 'print "$1\n" while /START(.*?)END/gs' file1 file2 ...

ولكن إذا كنت تريد الحوادث متداخلة من START من خلال END، عليك أن تسبق ضد المشكلة الموضحة في هذه المسألة في هذا القسم على مطابقة نص متوازن.

وهنا مثال آخر على استخدام ..:

while (<>) {
    $in_header =   1  .. /^$/;
    $in_body   = /^$/ .. eof;
# now choose between them
} continue {
    $. = 0 if eof;  # fix $.
}

كيف يمكنني انتزاع متعددة خطوط بعد خط مطابق في بيرل؟

وكيف يتم ذلك؟ في آن واحد، وسلسلة END هو $ ^، يمكنك تغييره إلى سلسلة END الخاص بك.

وأنا أيضا مبتدئ، ولكن الحلول هناك تقدم عدد غير قليل من الطرق ... اسمحوا لي أن أعرف على وجه التحديد ما هو عليه تريد أن يختلف عن الرابط أعلاه.

while (<>) {
    chomp;      # strip record separator
    if(/END/) { $f=0;}
    if (/START/) {
        s/.*START//g;
        $f=1;
    }
    print $_ ."\n" if $f;
}

ومحاولة كتابة بعض الرموز في المرة القادمة جولة

بعد تيليماكوس' الرد الأمور بدأت تتدفق.هذا يعمل ما الحل أنا أنظر بعد كل شيء.

  1. أحاول استخراج خطوط محددة من قبل اثنين من سلاسل (واحد مع خط النهاية مع "CINFILE=";الأخرى, مع خط تحتوي على واحد "#") في خطوط منفصلة ، باستثناء محدد خطوط.هذا لا يمكن القيام به مع تيليماكوس "حل".
  2. السطر الأول يحتوي على الفضاء الذي تريد إزالته.أنا أيضا ذلك.
  3. أنا أيضا أحاول استخراج كل خط مجموعة في ملفات منفصلة.

هذا يعمل بالنسبة لي, على الرغم من أن القانون يمكن أن تصنف على أنها قبيحة ؛ وهذا لأن أنا حاليا تقريبا الوافد الجديد إلى بيرل.على أي حال هنا المثل:

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

my $start='CINFILE=$';
my $stop='^#$';
my $filename;
my $output;
my $counter=1;
my $found=0;

while (<>) {
  if (/$start/../$stop/) {
    $filename=sprintf("boletim_%06d.log",$counter);
    open($output,'>>'.$filename) or die $!;
    next if /$start/ || /$stop/;
    if($found == 0) { print $output (split(/ /))[1]; }
    else { print $output $_; }
    $found=1;
  } else { if($found == 1) { close($output); $counter++; $found=0; } }
}

أتمنى أن يستفيد الآخرين كذلك.الهتافات.

وليس سيئا للغاية بالنسبة قادمة من "newcommer الظاهري". الشيء الوحيد الذي يمكن القيام به، هو وضع "وجدت $ = 1" داخل "إذا ($ جدت == 0)" كتلة بحيث كنت لا تفعل تلك المهمة في كل مرة بين $ يبدأ و$ تتوقف.

وشيء آخر ما هو قبيح قليلا، في رأيي، هو أن تقوم بفتح نفس filehandler في كل مرة تقوم بإدخال $ بدء / توقف $ كتلة.

وهذا يدل على طول الطريق حول ما يلي:

#!/usr/bin/perl

use strict;
use warnings;

my $start='CINFILE=$';
my $stop='^#$';
my $filename;
my $output;
my $counter=1;
my $found=0;

while (<>) {

    # Find block of lines to extract                                                           
    if( /$start/../$stop/ ) {

        # Start of block                                                                       
        if( /$start/ ) {
            $filename=sprintf("boletim_%06d.log",$counter);
            open($output,'>>'.$filename) or die $!;
        }
        # End of block                                                                         
        elsif ( /$end/ ) {
            close($output);
            $counter++;
            $found = 0;
        }
        # Middle of block                                                                      
        else{
            if($found == 0) {
                print $output (split(/ /))[1];
                $found=1;
            }
            else {
                print $output $_;
            }
        }

    }
    # Find block of lines to extract                                                           

}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top