Как мне распечатать определенный символ в файле после прочтения файла?
-
13-09-2019 - |
Вопрос
Я читаю файл, используя 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;
Решение
Поскольку это проверка кода, давайте пойдем по порядку:
#!/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>;
Другие советы
Вы печатаете $_
в обеих ветвях вашего предложения if.Избавьтесь от ветки else.
Предполагая, что «строка» в вашем вопросе равна «строке»:
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;