Большая проблема с настройкой @ARGV заключается в том, что это глобальная переменная. Также вы должны знать, что while (<>)
имеет специальные магические атрибуты . (чтение каждого файла в @ARGV
или обработка STDIN
, если @ARGV
пусто, проверка на определенность, а не на истинность). Чтобы уменьшить магию, которую нужно понять, я бы избегал ее, за исключением быстрых хакерских заданий.
Вы можете получить имя файла текущего файла, установив $ARGV
.
Вы можете не осознавать этого, но на самом деле вы воздействуете на две глобальные переменные, а не только на @ARGV
. Вы также нажимаете $_
. Очень и очень хорошая идея локализовать $_
.
Вы можете уменьшить влияние манипулирующих глобалов, используя local
для локализации изменений.
Кстати, есть еще одна важная, тонкая часть магии с <>
. Скажем, вы хотите вернуть номер строки совпадения в файл. Вы можете подумать, хорошо, проверьте perlvar и обнаружите, что $.
дает номер белья в последней доступной ручке - отлично. Но здесь скрывается проблема - $.
не сбрасывается между @ARGV
файлами. Это замечательно, если вы хотите узнать, сколько всего строк вы обработали, но не хотите знать номер строки для текущего файла. К счастью, есть простой трюк с eof
, который решит эту проблему.
use strict;
use warnings;
...
searchDir( 'foo' );
sub searchDir {
my $dirN = shift;
my $pattern = shift;
local $_;
my @fileList = grep { -f $_ } glob("$dirN/*");
return unless @fileList; # Don't want to process STDIN.
local @ARGV;
@ARGV = @fileList;
while(<>) {
my $found = 0;
## Search for pattern
if ( $found ) {
print "Match at $. in $ARGV\n";
}
}
continue {
# reset line numbering after each file.
close ARGV if eof; # don't use eof().
}
}
ПРЕДУПРЕЖДЕНИЕ : Я только что изменил ваш код в своем браузере. Я не запускал его, поэтому он может иметь опечатки, и, вероятно, не будет работать без небольшой настройки
Обновление : причина использования local
вместо my
заключается в том, что они делают совершенно разные вещи. my
создает новую лексическую переменную , которая видна только в содержащемся блоке и недоступна через таблицу символов. local
сохраняет существующую переменную пакета и связывает ее с новой переменной. Новая локализованная версия видна в любом последующем коде, пока мы не покинем вмещающий блок. См. perlsub: Временные значения через локальные () .
В общем случае создания новых переменных и их использования, my
является правильным выбором. local
подходит, когда вы работаете с глобальными переменными, но вы хотите убедиться, что не распространяете свои изменения на остальную часть программы.
Этот короткий скрипт демонстрирует локальный:
$foo = 'foo';
print_foo();
print_bar();
print_foo();
sub print_bar {
local $foo;
$foo = 'bar';
print_foo();
}
sub print_foo {
print "Foo: $foo\n";
}