Я пытался заставить свою программу Perl сортировать базу данных PDB по одному файлу за раз. Мне нужна программа, которая читает файл, выполняет небольшое сопоставление с образцом и, в зависимости от результата, перемещает файл в соответствующую папку без изменения имени файла. Пока что я придумал это:
#!/usr/bin/perl
use File::Basename;
@files = <top8000/rands/*> ;
$file = 0;
$count = 1;
while ( open (FILE, $files[$file]) )
{
while ( $FILEREAD = <FILE> )
{
if ( $FILEREAD =~ "pattern" )
{
$count++;
};
};
$string ="$files[$file]";
$filename = fileparse($string);
if ($count >=2 ) {
rename ( $files[$file] , "top8000/randsort/$filename.txt" );
};
$count = 1;
$file++;
};
Я знаю, что здесь я должен использовать my
перед переменными $string
и $filename
, но моя программа не работает с ним, и я действительно не понимаю, что он делает. Кроме того, я не могу понять, что не так с моей программой. Был бы признателен за любую помощь.
1 ответ
Что ж, похоже, вы сами себе все усложняете. Я предполагаю, что ваша проблема сейчас в том, что вы пытаетесь переименовать файл, который все еще открыт для чтения. Как правило, вы всегда должны проверять возвращаемое значение всех взаимодействий с файлами, например:
open my $fh, "<", $file or die "Cannot open file: $!";
rename $old, $new or die "Cannot rename: $!";
Потому что, вообще говоря, такие ошибки часто следует считать фатальными.
Вашу программу можно значительно упростить, используя некоторые встроенные функции:
use strict;
use warnings; # always use these two
use File::Copy qw(move);
@ARGV = <top8000/rands/*.txt> unless @ARGV; # default args
my $outdir = "top8000/randsort";
while (<>) { # read through the files
if (/pattern/) { # check each line
close ARGV; # close the file handle
move $ARGV, $outdir or die "Cannot move $ARGV: $!";
}
}
Как видите, вам не нужно указывать имя файла при использовании модуля File::Copy
: если адрес назначения - это папка, используется старое имя.
Мы используем ромбовидный оператор <>
, который при использовании использует либо стандартный входной дескриптор файла STDIN, либо - в нашем случае - открывает и читает файлы, указанные в качестве аргументов сценария в @ARGV
. А поскольку это Perl, мы можем делать все, что захотим, и просто вставлять аргументы по умолчанию, если их нет.
Поскольку ваш счетчик проверил 1 или несколько совпадений, это фактически то же самое, что просто переместить файл при первом совпадении, так почему бы этого не сделать? Просто убедитесь, что вы сначала закрыли файл! Дескриптор файла в этом случае - ARGV
. При этом также выполняется переход к следующему файлу в @ARGV
, что для нас очень удобно. Имя файла содержится в $ARGV
, и нам не нужно больше манипулировать им, поэтому нам больше не нужен модуль File::Basename
.
File::Copy
- это основной модуль Perl 5, поэтому установка не требуется.
Похожие вопросы
Новые вопросы
perl
Perl - это процедурный высокоуровневый динамический язык программирования общего назначения, известный своей собственной поддержкой регулярных выражений и возможностей синтаксического анализа строк. Пожалуйста, используйте этот тег для вопросов о Perl в целом. Для вещей, связанных с новым (но связанным) языком Raku (ранее «Perl 6»), используйте тег raku. Для регулярных выражений в стиле Perl на других языках используйте тег regex или, если они основаны на библиотеке PCRE, тег pcre.
file
иcount
(переменные без знака доллара перед$file
) или это просто проблема копирования / вставки?or die "Cannot rename: $!"
в конец вашего оператора переименования. Похоже, вы пытаетесь переместить файл, который все еще открыт для чтения.