HiveBrain v1.2.0
Get Started
← Back to all entries
patterngitMinor

Perl pie alternative

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
alternativepieperl

Problem

Running on Cygwin, I cannot easily use perl -pi -e because it will always produce .bak files even though I don't want them. I wrote this script below to emulate perl -pi -e behavior and unlink the backup files after processing.

Also I wanted to simplify the call of the script. Instead of:

$ git ls-files | xargs perl -pi -e s/foo/bar/


I rather prefer to write

$ git ls-files | pie s/foo/bar


Although this program is not aimed to be particularly used with Git, with this alias pie="!git ls-files | pie" it becomes

$ git pie s/foo/bar


I feel this script can be simplified and the performances could be slightly improved. The question is how.

#!/usr/bin/perl
use 5.010;
use strict;
use warnings;
use File::Copy;

my $re = shift @ARGV;
@ARGV  = split(/\n/, do {local $/; }) if @ARGV eq 0;

for my $file (@ARGV) {
    next unless -f $file;
    if (-f "$file.bak") {
        warn "[Warning] Backup file already exists and is been used by pie";
    }
    open my $fh,  "", "$file.bak";
    while () {
        eval($re);
    } continue { print $tmp $_ }
    close $tmp;
    close $fh;
    move "$file.bak", $file;
}

Solution

Ok, here is a solution with no additional modules, moving eval out of the loop, and with few additional checks.

use strict;
use warnings;

$^I = '.bak';
my $re = shift @ARGV or die "Nothing to do..";
$re = eval "sub{ $re }" or die "Incorrect expression..";

chomp(@ARGV  = ) if !@ARGV;
@ARGV = grep {
  warn "[Warning] Backup file already exists and is been used by pie"
    if -f "$_$^I";
  -f $_;
}
@ARGV;

my @bak = map "$_$^I", @ARGV;
while (<>) {
  $re->();
  print;
}
unlink(@bak);

Code Snippets

use strict;
use warnings;

$^I = '.bak';
my $re = shift @ARGV or die "Nothing to do..";
$re = eval "sub{ $re }" or die "Incorrect expression..";

chomp(@ARGV  = <STDIN>) if !@ARGV;
@ARGV = grep {
  warn "[Warning] Backup file already exists and is been used by pie"
    if -f "$_$^I";
  -f $_;
}
@ARGV;

my @bak = map "$_$^I", @ARGV;
while (<>) {
  $re->();
  print;
}
unlink(@bak);

Context

StackExchange Code Review Q#102037, answer score: 2

Revisions (0)

No revisions yet.