Question

Im trying to find specific pattern and do substitution in it. And assign result to another variable.

For example: I have a variable $text with some text in which Im trying to find pattern like "Date:\s+\d{4}.\d\d.\d\d", substitute dots for dashes in it and then assign result to $result.

This version works:

($result) = $text =~ /Date:\s+(\d{4}\.\d\d\.\d\d)/igs;
 $result =~ s/\./-/g;

But Im trying to do it in one operation. Something like:

($result) = $text =~ s/Date:\s+(\d{4})\.(\d\d)\.(\d\d)/$1-$2-$3/igs;

But it gives me result "1". So, the question is: Is it possible to do such thing in one operation? Or what is the best option to do it and minimize code?

Was it helpful?

Solution 2

You shouldn't be too keen on writing multiple operations into a single statement: it only serves to spoil the readability of your code. But I suggest that you write something like this.

There is no point in using the /s modifier on your original pattern match as it affects only the . metacharacter, and there are none of these in your pattern. Also, it makes no sense to use /g as you are interested only in a single match.

Don't be tempted to join the two statements into one line, as the if statement modifier would then also apply to the my declaration which has some very strange effects.

use strict;
use warnings;
use 5.010;

my $text = 'Date: 1994.04.04';

my $result;
$result = $1 =~ tr/./-/r if $text =~ /Date:\s+(\d{4}\.\d\d\.\d\d)/i;

say $text;
say $result;

output

Date: 1994.04.04
1994-04-04

OTHER TIPS

my $result;
$text =~ s/Date:\s+(\d{4})\.(\d\d)\.(\d\d)/ $result= "$1-$2-$3" /ei;

pls try this ($result = $text)=~s/Date:\s+(\d{4}).(\d\d).(\d\d)/$1-$2-$3/igs

If you move the parentheses around so that $text is first assigned to $result, you can then make the substitution apply to $result instead of $text, and so you can strip all the excess text you do not want, and use your original idea of building the date with dashes - instead of dots:

(my $result = $text) =~ s/.*Date:\s+(\d{4})\.(\d\d)\.(\d\d).*/$1-$2-$3/igs;

Note the use of .* at start and end of string, which will consume all of the text, so the only thing left is the date. This line of code is really two operations in one, like so:

my $result = $text;
$result =~ s/..../;

Another version is to use a post-script for loop, which will make use of the fact that $_ is aliased to the list arguments:

tr/./-/ for ((my $result) = $text =~ /Date:\s+([\d.]+)/);

This will assign the date to $result, and then pass $result to the argument list in for, applying the transliteration to it. It affects the real variable $result because $_ is aliased within the loop.

Also note that this is really an academic question, in my opinion. I would not recommend using this in production code, and your original is far better and more readable. Although I would use transliteration instead of a substitution:

$result =~ tr/./-/;
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top