Редактирование на месте нескольких файлов в каталоге с использованием Perl's diamond и оператора редактирования на месте - PullRequest
3 голосов
/ 10 февраля 2012

Я пытаюсь редактировать несколько текстовых файлов на месте, используя оператор редактирования Perl $ ^ I.Я просматриваю каталог, используя оператор diamond (<>), например:

$^I = ".bak";

@ARGV = <*.txt>;

while (<>)
{
    s/((?:^|\s)-?)(0+)(?=\s|$)/$1.$2/g;
    print;
}

Это отлично работает и выполняет ту работу, которая мне нужна.Но что, если мой @ARGV уже заполнен некоторыми другими данными, которые мне нужны для программы?Я пытался сделать следующее:

$^I = ".bak";

my @files = <*.txt>;

while (<@files>)
{
    s/((?:^|\s)-?)(0+)(?=\s|$)/$1.$2/g;
    print;
}

Но это не работает.Что мне здесь не хватает?Я не могу использовать свой $ ARGV, поскольку он содержит другие данные, и не могу связать его с шаблонами соответствия файлов.

Есть предложения?

Спасибо!

Ответы [ 5 ]

4 голосов
/ 10 февраля 2012

Вы можете присвоить @ARGV временное значение с ключевым словом local:

{
    local @ARGV = <*.txt>;
    while (<>) {...}
} # @ARGV gets the old value back
4 голосов
/ 10 февраля 2012

Вы можете заранее скопировать свои аргументы, а затем использовать @ARGV. E.g.:

my @args = @ARGV;
@ARGV = <*.txt>;

Поскольку происходит некоторая скрытая обработка, которая специфична для использования @ARGV и оператора diamond <>, вы не можете просто использовать другой массив для того же.

2 голосов
/ 10 февраля 2012

Не могли бы вы просто сохранить информацию из @ARGV, которая вам все еще нужна, в другую переменную?

$^I = ".bak";

my @options = @ARGV;
@ARGV = <*.txt>;

while (<>)
{
    s/((?:^|\s)-?)(0+)(?=\s|$)/$1.$2/g;
    print;
}
0 голосов
/ 12 февраля 2012

Мой обычный подход для этого - обработать аргументы и сохранить файлы во временном списке, а затем вставить их обратно в @ ARGV.

my @files;
foreach (@ARGV) {
    ... do something with each parm
    else {
        push @files,$_;
    }
}
@ARGV=@files;
while (<>) {
    ...

Обычно в foreach (@ARGV) Iбудет делать что-то вроде

if (-f) {
    push @files,$_;
    next;
}
0 голосов
/ 11 февраля 2012

Я бы использовал Iterator :: Files, см. http://search.cpan.org/perldoc/Iterator::Diamond по причинам, почему

use Iterator::Files;
my $input = Iterator::Files->new( files => [ glob "*.txt" ] );
while( <$input> ){
    s/((?:^|\s)-?)(0+)(?=\s|$)/$1.$2/g;
    print;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...