Нулевой файловый дескриптор <>
является особенным: его можно использовать для эмуляции поведения sed и awk. Ввод из <>
происходит либо из стандартного ввода, либо из каждого файла, указанного в командной строке. Вот как это работает: при первом вычислении <>
проверяется массив @ARGV
, а если он пуст, $ARGV[0]
устанавливается на "-", что при открытии дает вам стандарт вход. Массив @ARGV
затем обрабатывается как список имен файлов. Петля
while (<>) {
... # code for each line
}
эквивалентен следующему Perl-подобному псевдокоду:
unshift(@ARGV, '-') unless @ARGV;
while ($ARGV = shift) {
open(ARGV, $ARGV);
while (<ARGV>) {
... # code for each line
}
}
за исключением того, что это не так громоздко, и на самом деле будет работать. Это действительно смещает массив @ARGV
и помещает текущее имя файла в переменную $ARGV
. Он также использует файловый дескриптор ARGV
для внутреннего использования. <>
- это просто синоним <ARGV>
, что волшебно. (Приведенный выше псевдокод не работает, поскольку он обрабатывает <ARGV>
как немагический.)
Поскольку нулевой файловый дескриптор использует форму открытия с двумя аргументами, он интерпретирует специальные символы, поэтому, если у вас есть такой скрипт:
while (<>) {
print;
}
и вызов его с помощью perl dangerous.pl 'rm -rfv *|'
, он фактически открывает канал, выполняет команду rm
и считывает вывод rm
из этого канала. Если вы хотите, чтобы все элементы в @ARGV
интерпретировались как имена файлов, вы можете использовать модуль ARGV :: readonly из CPAN.
Вы можете изменить @ARGV
перед первым <>
, пока массив заканчивается списком имен файлов, которые вам действительно нужны. Номера строк ($.
) продолжаются, как если бы ввод был одним большим счастливым файлом. См. Пример в eof о том, как сбросить номера строк в каждом файле.