Обработка аргументов командной строки осуществляется через встроенный массив @ARGV, который содержит все параметры, переданные скрипту при запуске (кроме имени самого скрипта). Это базовый способ для любых CLI Perl-приложений, но в нем много нюансов, связанных с типами данных, кодировкой, разделением параметров и подводными камнями автосчитывания файлов.
С первых версий Perl массив @ARGV представлял стандартную "точку входа" в аргументы запуска, аналогично argv[] в C. Однако Perl, будучи языком общего назначения и текстовых задач, добавил множество дополнительных трюков — например, выражение <>, которое "связано" с содержимым @ARGV, позволяя сразу читать файлы, перечисленные как аргументы.
Тривиальное чтение @ARGV годится только для простых случаев. В сложных CLI-программах появляется задача обработки опций (типа --help, -o file). Тут простое чтение данных по индексам становится небезопасным и неудобным. Ещё сложнее становится с обработкой аргументов, содержащих пробелы, нестандартные символы или в разных кодировках. Плюс, есть вопросы с автоматическим открытием файлов через оператор <> и неожиданным поведением, если элементы @ARGV равны, например, "-" (stdin).
Чтение простых аргументов:
foreach my $arg (@ARGV) { print "Arg: $arg "; }
Обычно для опций применяют специальный модуль Getopt::Long:
use Getopt::Long; my $help; GetOptions('help' => \$help);
Для чтения всех файлов из @ARGV содержимое файлов можно сразу читать через цикл:
while (<>) { print; }
Что будет, если один из аргументов командной строки содержит только дефис (-)?
В этом случае при использовании оператора <> Perl воспринимает '-' как стандартный ввод (stdin), а не имя файла.
perl script.pl - file.txt # Чтение сначала из stdin, потом из file.txt
Можно ли безопасно модифицировать @ARGV внутри скрипта?
Да, это стандартная практика для удаления уже обработанных аргументов. Обычно после обработки опций @ARGV оставляют только "голые" имена файлов или нераспознанные параметры.
Нужно ли делать encode/decode при работе с UTF-8 аргументами в @ARGV?
Это зависит от локали и окружения. По умолчанию Perl не преобразует кодировки @ARGV, а принимает "как есть". Поэтому если имена файлов (или параметры) содержат не-ASCII символы, желательно явно декодировать строки с помощью Encode, если требуется работа с ними в Perl.
Утилита для парсинга логов принимает список файлов. Пользователь случайно указывает '-':
perl parse.pl - access.log
как результат — внезапно программа застопорилась и ждет ввода с клавиатуры.
Плюсы:
Минусы:
CLI-программа читает аргументы через Getopt::Long, явно обрабатывает все минусовые опции, оставляя в @ARGV только имена файлов:
perl report.pl --input access.log --output report.txt
Плюсы:
Минусы: