Xonotic Forums
Perl help - Printable Version

+- Xonotic Forums (https://forums.xonotic.org)
+-- Forum: Community (https://forums.xonotic.org/forumdisplay.php?fid=6)
+--- Forum: Off Topic (https://forums.xonotic.org/forumdisplay.php?fid=15)
+--- Thread: Perl help (/showthread.php?tid=2889)



Perl help - Spaceman - 04-14-2012

I want to rename some files from foo.jpg.1 to foo.jpg. They all have a numeric extension and can be jpeg, jpe or jpg.

Why doesn't this (air) code work?

Code:
#!/usr/bin/perl
# use strict;
# use warnings;

my $name = $_;
my $file_ext_original = ($name =~ m/([^.]+)$/)[0];

if($file_ext_original eq ["1", "2", "3", "4", "5", "6", "7", "8", "9"]) {
    print "$name needs to be renamed\n";
} else {
    print "$name is good\n";
}

Is it possible to use this string comparison or something like it?
Code:
$file_ext_original eq ["1", "2", "3", "4", "5", "6", "7", "8", "9"]

Instead I used a simple switch (again some air code)
Code:
use 5.010;

given ($file_ext_original) {
    when (["1", "2", "3", "4", "5", "6", "7", "8", "9"]) {
        print "$name needs to be renamed\n";
    }
    default {
#        print "$name is good\n";
    }
}



RE: Perl help - Mr. Bougo - 04-14-2012

Why not use
Code:
$file_ext_original ~= /[0-9]/

What you're doing with ["1", "2", ... , "9"] is create an array ref pointing to an array cointaining 1, ..., 9. You're comparing an array ref to a scalar. Even if you provided an array instead of an array ref by using parentheses instead of brackets, the array would be interpreted in scalar context, which means you would be comparing your lhs with the array's length, i.e. 9. To do exactly what you seem to be wanting to do, you need to use grep, or the smart matching operator ~~ which basically works as a shorthand for grep in that context. EDIT: but don't use an array ref, use an actual array.

EDIT: oops, smart matching implicitly dereferences array refs, so it works just fine with array refs. And given/when uses smart matching, so that explains why your array ref comparison is "smart" and works.


RE: Perl help - Spaceman - 04-18-2012

Cheers MrBougo Angel Angel

I was hoping to create an array and then use a simple comparison to check if any of the array elements equalled $file_ext_original.
Code:
$file_ext = "mp3";
@array = qw(mp3 png jpg jpeg par2);

if ($file_ext == @array) {
    print "$file_ext is wanted\n";
} else {
    print "$file_ext: unknow\n";
}

A simple foreach works, but...
Code:
my $element = "";
my $file_ext = "mp3";
my @array = qw(png jpg mp3 jpeg par2);

foreach $element (@array) {
    if ($file_ext eq $element) {
        print "$file_ext is wanted\n";
    } else {
        print "$file_ext: unknow\n";
    }
}

# only using numbers
$file_ext = "7";
@array = (1..10);

foreach $element (@array) {
    if ($file_ext eq $element) { # eq or ==
        print "$file_ext is wanted\n";
    } else {
        print "$file_ext: unknow\n";
    }
}
its ugly.

Unfortunately Perl regex's are very greedy and confused.
Code:
@array = qw(mp3 m3p 3mp);
push(@array, (1..10));

foreach $element (@array) {
    if ($element =~ /[0-9]/) {
        print "a: $element has a number\n";
    }
}
print "\n\n";
foreach $element (@array) {
    if ($element =~ /^[0-9]+$/) {
        print "b: $element is +ve integer\n";
    }
}

Using smart matching
Code:
my @array = (1..20);
foreach my $element (@array) {
    if($element ~~ ["1", "2", "3", "4", "5", "8", "9", "10"]) {
        print "$element needs to be renamed\n";
    } else {
        print "$element is good\n";
    }
}



RE: Perl help - Mr. Bougo - 04-18-2012

Smart matching does not need array refs, and you could simply use (1..10) in the rhs.

For the regex one, why don't you match the whole file name against /\.(.+?)\.[0-9]+$/ and then grep for $1 in @array? +? means non-greedy +, it'll take the shortest match it finds.

EDIT: actually, why not just rename $file to the match of $file =~ s/(.*\.(?:mp3|jpg|blah|bleh)\.[0-9]+/ ?