Как использовать расширение параметров оболочки в Perl? - PullRequest
1 голос
/ 29 апреля 2020

Я пытаюсь реализовать метод расширения параметров Bash, чтобы заменить существующее расширение файла в сценарии Perl.

Это мой bash код для замены расширения файла, который работает нормально:

mv "$f" "${f%.*}.png"

С другой стороны, я пытаюсь использовать его в скрипте Perl, используя system():

system('mv', "$a/$fileName", "$a/${fileName%.*}".'.png');

$a содержит имя каталога, которое передается с помощью аргумента командной строки.

Выдает "syntax error near %", за которым следует "missing right curly or square bracket within string". В сообщении об ошибке нет EOF.

Когда я не использую %.*, он просто добавляет .png после окончания существующего файла, но не заменяет. Некоторая помощь будет высоко оценена.

Ответы [ 3 ]

5 голосов
/ 29 апреля 2020

Таким образом, вы можете sh заменить расширение - изменить имя файла. Нет смысла обращаться к оболочке для этого, когда вы находитесь в Perl скрипте.

Смена расширения легко выполняется «вручную» (библиотеки см. Ниже). С регулярным выражением

my $new_filename = $filename =~ s/.*\.\K.*/$new_extension/r;

.* жадно совпадает до самого последнего . (что следует в схеме), а затем \K отбрасывает все совпадения, так что мы заменяем только то, что следует после него , Или используйте привязку конца строки $

my $new_filename = $filename =~ s/\.\K[^.]+$/$new_extension/r;

, которая соответствует и заменяет все не . символы в конце строки после .. В обоих случаях модификатор /r заставляет его возвращать новую строку и оставлять оригинал без изменений; без него строка ($filename) была бы изменена на месте.

Теперь измените имя файла на диске. Стандартный инструмент - File :: Copy

use File::Copy qw(move);

move $filename, $new_filename  or die "Can't move: $!";

(Если вы заметили встроенное переименуйте , сохраняйте спокойствие и проходите мимо него. Это странно и " сильно различается . ")


Самый общий способ solid - это, конечно, использование подходящих библиотек, и есть хорошие, которые могут быть использованы для этого. Вот с полезным Path :: Tiny (который вам нужно установить)

use Path::Tiny;

my $path = path($filename);

my $new_fqn = $path->parent->child( $path->basename(qr/[^.]+/) . $new_ext );

См. Связанную документацию для этого модуля, но здесь есть краткое объяснение выше.

Метод parent возвращает путь до последнего компонента (файл / каталог) в виде объекта Path::Tiny. Затем вызванный метод child добавляет к нему еще один компонент.

Для этого мы получаем basename (последний компонент, с расширением, удаленным в этом использовании), а затем добавляем новое расширение к нему. И вуаля, мы возвращаем весь путь с заменой расширения. Это анализирует путь дважды, один раз для parent и один раз для basename.

Дополнительным преимуществом этого является то, что модуль также имеет метод move, поэтому

$path->move($new_fqn);

заканчивает работу.

Модуль проверяет наличие ошибок и либо croaks, либо выдает исключение своего собственного класса .


Старый и проверенный UNIX способ используя ядро ​​ File :: Basename

use File::Basename;

my ($name, $path, $ext) = fileparse($filename, qr/\.[^.]*/); 

my $new_fqn = "$path/$name.$new_ext";

Затем используйте File::Copy::move для переименования файла.

1 голос
/ 29 апреля 2020

Не используйте синтаксис Bash и Perl одновременно, оба языка имеют неясный синтаксис, их одновременное использование ухудшает ситуацию.

Bash:

"${f%.*}.png"

Perl: Использовать File :: Basename module https://perldoc.perl.org/File/Basename.html

$f_new=fileparse($f_old,qr/\.[^.]*/);
$f_new.=".png";

Bash:

mv

Perl:

rename / File::Copy (see comment)

Собрать вместе (демонстрация в одну строку - Perl): переименовать foo.jpg в foo.png

Использование переименования:

$ perl -MFile::Basename -e '$f_old=$ARGV[0];$f_new=fileparse($f_old,qr/\.[^.]*/);$f_new.=".png";rename $f_old, $f_new' foo.jpg

Использование Файл :: Копировать

$ perl -MFile::Copy -MFile::Basename -e '$f_old=$ARGV[0];$f_new=fileparse($f_old,qr/\.[^.]*/);$f_new.=".png";File::Copy::move $f_old, $f_new' foo.jpg
0 голосов
/ 29 апреля 2020

В Perl есть строки в двойных кавычках, что означает, что $variables интерполируется внутри Perl. Это похоже на запись в Perl

my $xx="abc"
my $yy=${xx%.*}

Вы получите ту же ошибку.

...