PDA

View Full Version : [SOLVED] Basic Perl text substitution



hailholyghost
May 21st, 2012, 05:48 PM
Hello,

I would like to combine these two Perl substitutions


my $name = $file;
$name =~ s/.out$//;
$name =~ s/^nmr//;

into a single command, just like sed can do:


sed -e 's/^nmr//g' -e 's/out$//g'

I know that Perl was meant to mimic the way that sed works, but it doesn't work *exactly* the same.

The program I have now works, but I would like to make it better.

Thanks very much!

trent.josephsen
May 21st, 2012, 08:14 PM
Like this?


perl -pe 's/.out$//; s/^nmr//'

wallaroo
May 22nd, 2012, 01:43 AM
How about ..

$name =~ s/.out$|^nmr//g;

hailholyghost
May 22nd, 2012, 01:41 PM
Hi wallaroo,

Yep that worked!

Thanks so much!

and to trent.josephsen, I should have specified that I meant with a perl text file. My bad!

-Dave

shawnhcorey
May 22nd, 2012, 01:41 PM
Hello,

I would like to combine these two Perl substitutions


my $name = $file;
$name =~ s/.out$//;
$name =~ s/^nmr//;

into a single command, just like sed can do:


sed -e 's/^nmr//g' -e 's/out$//g'

I know that Perl was meant to mimic the way that sed works, but it doesn't work *exactly* the same.

The program I have now works, but I would like to make it better.

Thanks very much!

Why? Doing so makes your code harder to understand. Avoid micro-optimization; it never improves the code.

trent.josephsen
May 22nd, 2012, 04:32 PM
shawnhcorey is correct; combining the two into a single substitution is not an improvement (and will probably hurt your performance rather than the reverse).

Also, I'd like to observe that . matches any character, so your first substitution will change 'about' to 'a'. If you want to match a literal ., escape it.

David Andersson
May 22nd, 2012, 06:22 PM
I would like to combine these two Perl substitutions


my $name = $file;
$name =~ s/.out$//;
$name =~ s/^nmr//;

into a single command

All the answers above are correct and works. My answer is a different approach.

If we look at it as idioms, the above is basically "remove things we don't want" so at the end "what remains is what we want". I'll suggest "pick out what we want" and in this case "express what we want by its context".


if ($file =~ m/^nmr(.*)\.out$/) {
$name = $1;
}

The thing in parenthesis is captured in variable $1 (and $2 etc).

This pick things behaves slightly different in certain cases, compared to the remove things. If $file does not match, $name will be unset, instead of being a copy of $file. If that is good or bad depends on the rest of the program. For example, if it would be an error for $file not to have "nmr" and ".out" in it the code could be extended like this:


if ($file =~ m/^nmr(.*)\.out$/) {
$name = $1;
} else {
die "file name didn't contain a name\n";
}


Another example (where both context and content matters): if $name must be a number, then change the pattern to ^nmr(\d+)\.out$ .