كيف يمكنني طباعة حرف معين في الملف بعد قراءة الملف؟

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

سؤال

أنا أقرأ ملف باستخدام البرنامج النصي بيرل. يتكون هذا الملف من سلاسل بأحرف مختلفة وأريد تحديد السلاسل التي تحتوي على الحرف "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;
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top