Normally when I check if the regex succeeded I do
if ($var =~ /aaa(\d+)bbb(\d+)/) { # $1 and $2 should be defined now }
but I recall seeing a variation of this that seamed shorter. Perhaps it was only with one buffer.
Can anyone think or other ways to test if $1 after a successful regex?
You can avoid $1 and similar altogether:
if (my ($anum, $bnum) = $var =~ /aaa(\d+)bbb(\d+)/) {
# Work with $anum and $bnum
}
The only shorter way that I can think of is if the match is on $_. So for instance:
for (#strings) {
if (m/aaa(\d+)bbb(\d+)/) {
...
If the match succeeds then $1 and $2 will be populated.
never forget about
use strict;
use warnings;
I like plain syntax in Perl, but not in this way:
my $str = 'abc101abc';
$str =~ m/(\d+)/ and do {print $1;}
OR
$str =~ m/(\d+)/ and print $1;
OR
($str in $_, so $_ = $str;)
m/(\d+)/ and print $1;
BUT! TIMTOWTDI helps you to dream about your own style :)
I prefer old-if style.
Reading both answers, I now recall that this was what I had seen
my $str = 'abc101abc';
$str =~ m/(\d+)/;
print $1 if $1;
print $1 if $str =~ m/(\d+)/;
Related
I realize it is possible to achieve this with a slight workaround, but I am hoping there is a simpler way (since I often make use of this type of expression).
Given the example string:
my $str = "An example: sentence!*"
A regex can be used to match each punctuation mark and capture them in an array.
Thereafter, I can simply repeat the regex and replace the matches as in the following code:
push (#matches, $1), while ($str =~ /([\*\!:;])/);
$str =~ s/([\*\!:;])//g;
Would it be possible to combine this into a single step in Perl where substitution occurs globally while also keeping tabs on the replaced matches?
You can embed code to run in your regular expression:
my #matches;
my $str = 'An example: sentence!*';
$str =~ s/([\*\!:;])(?{push #matches, $1})//g;
But with a match this simple, I'd just do the captures and substitution separately.
Yes, it's possible.
my #matches;
$str =~ s/[*!:;]/ push #matches, $&; "" /eg;
However, I'm not convinced that the above is faster or clearer than the following:
my #matches = $str =~ /[*!:;]/g;
$str =~ tr/*!:;//d;
Use:
my $str = "An example: sentence!*";
my #matches = $str =~ /([\*\!:;])/g;
say Dumper \#matches;
$str =~ tr/*!:;//d;
Output:
$VAR1 = [
':',
'!',
'*'
];
Is that what you're looking for ?
my ($str, #matches) = ("An example: sentence!*");
#first method :
($str =~ s/([\*\!:;])//g) && push(#matches, $1);
#second method :
push(#matches, $1) while ($str =~ s/([\*\!:;])//g);
Try:
my $str = "An example: sentence!*";
push(#mys, ($str=~m/([^\w\s])/g));
print join "\n", #mys;
Thanks.
Can someone tell me why my script below search/replace when I am using \Q$btype when it works when I hard code with center instead?
The script is suppose to insert $$ after \end{center}.
#!/usr/bin/perl
my $line = '\end{tabular}
\end{center}
end:text
';
my $btype = "center";
$line =~ s/\\end\{\Q$btype\}/\\end\{\Q$btype\}\$\$/g;
print "$line\n";
You need to stop the escaping:
$line =~ s/\\end\{\Q$btype\E\}/\\end\{$btype\}\$\$/g;
# here __^^
it could be reduce to:
$line =~ s/\\end\{\Q$btype\E\}\K/\$\$/g; # 5.10+
or
$line =~ s/(\\end\{\Q$btype\E\})/$1\$\$/g;
or
$line =~ s/\\end\{\Q$btype\E\}/$&\$\$/g;
From ThisSuitIsBlackNot's comment:
Don't use it with perl before v5.20 because of performance issue.
or
$line =~ s/(?<=\\end\{\Q$btype\E\})/\$\$/g;
How can I run regexp more times on same variable?
I want
$$contRef =~ /Kurs.*?(\d+,?\d*)<\/span/msgi;
and
$$contRef =~ /Price(\d+,?\d*)<\/span/msgi;
IIRC regexp sets a pointer and If I want to find any pattern again and start from the beginning I need to reset the variable. I don't want to copy the content to other variable.
I wish to reset the pointer to be able to start the searching from the beginning.
What you're looking for is exactly what you just pasted.
$$contRef =~ /Kurs.*?(\d+,?\d*)<\/span/msgi;
# Do stuff with $1
# ...
# ...
$$contRef =~ /Price(\d+,?\d*)<\/span/msgi;
# Do new stuff with the new $1
# ...
# ...
Maybe your unusual use of variables is the problem? This works and prints 9922
$a="Kursplat99</spanPrice22</span";
$contRef = "a";
$$contRef =~ /Kurs.*?(\d+,?\d*)<\/span/msgi;
print $1;
$$contRef =~ /Price(\d+,?\d*)<\/span/msgi;
print $1;
As has been suggested in the comments, perhaps a while, alternation (|) and an array for the captures would be helpful here:
use strict;
use warnings;
use Data::Dumper;
my $string = "Kursplat99</span>Price22</span";
my #array;
push #array, $1 while $string =~ /(?:Kurs.*?|Price)(\d+,?\d*)<\/span/msgi;
print Dumper \#array if #array;
Output:
$VAR1 = [
'99',
'22'
];
I'm sure there is a very simple way to do this, but whenever I search for examples, I get the two step method. Here is what I typically do:
$data =~ m/(my_query)/;
$result = $1;
I want to set $result in the same line as the regex and never use $1. Thanks!
my($result) = ($data =~ m/(my_query)/);
As noted in a comment, the my($result) needs the parentheses to provide an array context for the result of the match. In an array context, you get the $1 etc allocated to the array. You could use #result = ($data =~ m/(my_query)/);; you could omit the my but you would need to keep the parentheses; you could subscript the array using $result = ($data =~ m/(my_query)/)[0]; (thanks ysth). The key words here are 'array context'.
Examples:
$ perl -e '$data="abcdef";my($result)=($data =~ m/(cde)/); print "$result\n"'
cde
$ perl -e '$data="abcdef"; ($result)=($data =~ m/(cde)/); print "$result\n"'
cde
$ perl -e '$data="abcdef"; #result =($data =~ m/(cde)/); print "$result[0]\n"'
cde
$ perl -e '$data="abcdef"; $result =($data =~ m/(cde)/)[0]; print "$result\n"'
cde
$
You didn't specify what problem you want to avoid, but there is definitely one to avoid. The following code assigns something unknown to $result when the pattern doesn't match:
$data =~ /(my_query)/;
my $result = $1;
You could use a conditional to assign something useful to $result when the pattern doesn't match
my $result = $data =~ /(my_query)/ ? $1 : undef;
Or you could take advantage of the fact that m// in list context returns what it captured.
my ($result) = $data =~ /(my_query)/;
$data="abcde";
$data =~ s/(cde)/$result=$1/e;
Noob question here. I have a very simple perl script and I want the regex to match multiple parts in the string
my $string = "ohai there. ohai";
my #results = $string =~ /(\w\w\w\w)/;
foreach my $x (#results){
print "$x\n";
}
This isn't working the way i want as it only returns ohai. I would like it to match and print out ohai ther ohai
How would i go about doing this.
Thanks
Would this do what you want?
my $string = "ohai there. ohai";
while ($string =~ m/(\w\w\w\w)/g) {
print "$1\n";
}
It returns
ohai
ther
ohai
From perlretut:
The modifier "//g" stands for global matching and allows the
matching operator to match within a
string as many times as possible.
Also, if you want to put the matches in an array instead you can do:
my $string = "ohai there. ohai";
my #matches = ($string =~ m/(\w\w\w\w)/g);
foreach my $x (#matches) {
print "$x\n";
}
Or you could do this
my $string = "ohai there. ohai";
my #matches = split(/\s/, $string);
foreach my $x (#matches) {
print "$x\n";
}
The split function in this case splits on spaces and prints
ohai
there.
ohai