كيف يمكنني طباعة حرف معين في الملف بعد قراءة الملف؟
-
13-09-2019 - |
سؤال
أنا أقرأ ملف باستخدام البرنامج النصي بيرل. يتكون هذا الملف من سلاسل بأحرف مختلفة وأريد تحديد السلاسل التي تحتوي على الحرف "x". أريد أن أعرف كيف أنا (1) طباعة هذه السلسلة (تحتوي على 'x') وكذلك (2) اكتب هذه السلسلة إلى ملف آخر (3) عد عدد أحرف "X" في الملف بأكمله. وبعد البرنامج النصي أدناه يطبع الملف بأكمله مرة أخرى. أي اقتراحات؟
#!/use/bin/perl
use strict;
use warnings;
open (FILE, "/home/user/Desktop/infile.phy") || die "cant open file\n";
my @body = <FILE>;
close (FILE);
my $count= 0;
my $string = '';
foreach $_(@body){
if ($_ =~ m/[X]/){
print "$_";
$count++;
print $count;
}
else {
print ;
}
}
exit;
المحلول
نظرا لأن هذا مراجعة التعليمات البرمجية، فلنذهب واحدا تلو الآخر:
#!/use/bin/perl
أن خط shebang هو على الأرجح خطأ مطبعي. ربما يجب أن يكون
#!/usr/bin/perl
أو أيا كان which perl
يعود على نظامك.
use strict;
use warnings;
جيد.
open (FILE, "/home/user/Desktop/infile.phy") || die "cant open file\n";
لا حاجة للحزمة Filehandles Global FileHandles عندما يمكنك استخدام Filehandles Lexical. شكل 3 حجة من open
هو الأفضل هذه الأيام. أيضا، يجب أن تشير رسالة الخطأ إلى الملف الذي لا يمكنك فتحه:
my $filename = '/home/user/Desktop/infile.phy';
open my $input, '<', $filename
or die "Cannot open '$filename' for reading: $!";
my @body = <FILE>;
أنت تضع الملف في صفيف. هذا غير ضروري تماما في هذه الحالة.
my $count = 0;
my $string = '';
أعلن وتهيئة (إذا لزم الأمر) أي متغيرات في أصغر نطاق ممكن.
my $count;
المتغير $string
لا يستخدم في أي مكان آخر في التعليمات البرمجية الخاصة بك.
foreach $_(@body){
هذا سخيف. for
يستخدم $ _ إذا لم يتم تحديد متغير حلقة. من الأسهل الاحتفاظ بالأشياء مباشرة إذا حددت بدلا من ذلك متغير حلقة معجمية.
for my $line ( @body ) {
ومع ذلك، لا أعتقد أنك يجب أن تطلب الملف.
if ($_ =~ m/[X]/){
يؤدي ذلك إلى تطابق ناجح إذا كان الخط يحتوي على X. لذلك، فإنه يعادل /X/
. وبعد ومع ذلك، لن يخبرك بالكلمة الواردة في "X". لذلك، عليك أن تقرر ما هي الكلمة وتفعل مطابقتك على مستوى الكلمة.
مع كل ذلك في الاعتبار، النظر في البرنامج النصي التالي. لقد اتخذت افتراض تبسيط فيما يتعلق بما أعتبره كلمة. يجب أن تكون قادرا على البناء على هذا لإرضاء جميع المتطلبات:
#!/usr/bin/perl
use strict;
use warnings;
my $filename = "$ENV{TEMP}/test.txt";
open my $input, '<', $filename
or die "Cannot open '$filename' for reading: $!";
my $count;
while ( my $line = <$input> ) {
my @words = grep { /X/ } split /\b/, $line;
$count += @words;
print join(', ', @words), "\n";
}
print "$count\n";
__END__
تحديث: إذا كنت لا تهتم بإيجاد الكلمات داخل كل سطر يحتوي على أحرف X واحدة أو أكثر، فسيتم تبسيط الحلقة أثناء التشغيل:
while ( <$input> ) {
$count += (my @matches = /(X)/g );
print if @matches;
}
باستخدام $ _. ومع ذلك، ربما يكون ذلك غير فعال (بالنظر إلى أننا نقوم بحفظ كل حرف X مطابق). في هذه الحالة، tr
يعمل بشكل أفضل:
my ($count, $n);
$n = tr/X// and $count += $n and print while <$input>;
نصائح أخرى
أنت تطبع $_
في كل من فروعك إذا كان بند الخاص بك. تخلص من الفرع آخر.
على افتراض "سلسلة" في سؤالك يساوي "الخط":
use strict;
use warnings;
@ARGV=qw(/home/user/Desktop/infile.phy);
my $count = 0;
open my $outfile, '>', 'outfile' or die $!;
while (<>) {
my $cnt = tr/X/X/;
if ($cnt) {
print;
print $outfile $_;
}
$count += $cnt;
}
close $outfile or die $!;
print $count;