كيف يمكنني استخراج خطوط بين اثنين من خط المحددات في بيرل?
سؤال
لدي 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;
}
ومحاولة كتابة بعض الرموز في المرة القادمة جولة
بعد تيليماكوس' الرد الأمور بدأت تتدفق.هذا يعمل ما الحل أنا أنظر بعد كل شيء.
- أحاول استخراج خطوط محددة من قبل اثنين من سلاسل (واحد مع خط النهاية مع "CINFILE=";الأخرى, مع خط تحتوي على واحد "#") في خطوط منفصلة ، باستثناء محدد خطوط.هذا لا يمكن القيام به مع تيليماكوس "حل".
- السطر الأول يحتوي على الفضاء الذي تريد إزالته.أنا أيضا ذلك.
- أنا أيضا أحاول استخراج كل خط مجموعة في ملفات منفصلة.
هذا يعمل بالنسبة لي, على الرغم من أن القانون يمكن أن تصنف على أنها قبيحة ؛ وهذا لأن أنا حاليا تقريبا الوافد الجديد إلى بيرل.على أي حال هنا المثل:
#!/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
}