Golam Kawsar
Golam Kawsar

Reputation: 780

In-place editing of multiple files in a directory using Perl's diamond and in-place edit operator

I am trying to in-place edit a bunch of text files using Perl's in-place edit operator $^I. I traverse through the directory using the diamond (<>) operator like this:

$^I = ".bak";

@ARGV = <*.txt>;

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

This works perfectly and does the job I need it to do. But what if my @ARGV is already populated with some other data I need for the program? I tried to do the following:

$^I = ".bak";

my @files = <*.txt>;

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

But it does not work. What I am I missing here? I can't use my $ARGV as it contains other data and can't mess it with file matching patterns.

Any suggestions?

Thanks!

Upvotes: 4

Views: 1246

Answers (5)

mswanberg
mswanberg

Reputation: 1285

My usual approach for this is to process the arguments and save the files off in a temporary list, then stuff them back into @ARGV.

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

Usually, in the foreach (@ARGV) I will do something like

if (-f) {
    push @files,$_;
    next;
}

Upvotes: 0

obmib
obmib

Reputation: 476

I would use Iterator::Files, see http://search.cpan.org/perldoc/Iterator::Diamond for reasons why

use Iterator::Files;
my $input = Iterator::Files->new( files => [ glob "*.txt" ] );
while( <$input> ){
    s/((?:^|\s)-?)(0+)(?=\s|$)/$1.$2/g;
    print;
}

Upvotes: 0

dkniffin
dkniffin

Reputation: 1383

Couldn't you just store the information from @ARGV that you still need into another variable?

$^I = ".bak";

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

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

Upvotes: 2

TLP
TLP

Reputation: 67900

You can copy your arguments beforehand, and then use @ARGV. E.g.:

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

Since there is some hidden processing going on, which is specific to the use of @ARGV and the diamond operator <>, you cannot just use another array to do the same thing.

Upvotes: 4

Eric Strom
Eric Strom

Reputation: 40142

You can give @ARGV a temporary value with the local keyword:

{
    local @ARGV = <*.txt>;
    while (<>) {...}
} # @ARGV gets the old value back

Upvotes: 4

Related Questions