Как распечатать определенный символ в файле после прочтения файла? - PullRequest
0 голосов
/ 09 июня 2009

Я читаю файл, используя Perl-скрипт. Этот файл состоит из строк с разными символами, и я должен идентифицировать строки, содержащие символ «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;

Ответы [ 3 ]

4 голосов
/ 09 июня 2009

Так как это обзор кода, давайте пойдем один за другим:

#!/use/bin/perl

Эта линия Шебанга, скорее всего, опечатка. Вероятно, должно быть

#!/usr/bin/perl

или что-то еще which perl возвращается в вашу систему.

use strict;
use warnings;

Хорошо.

open (FILE, "/home/user/Desktop/infile.phy") || die "cant open file\n";

Нет необходимости в пакетных глобальных файловых дескрипторах, когда вы можете использовать лексические файловые дескрипторы. Форма с тремя аргументами 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 будет упрощен:

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>;
1 голос
/ 09 июня 2009

Вы печатаете $_ в обеих ветвях вашего условия if. Избавьтесь от ветки else.

0 голосов
/ 09 июня 2009

Предполагая, что "строка" в вашем вопросе равна "строке":

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;
...