note
haukex
<p>You will find the answer to your question in [doc://perlop#Regexp-Quote-Like-Operators|"Regexp Quote-Like Operators" in perlop] - basically, different regex operations have different return values in different contexts. See also [doc://perlretut] for a tutorial.</p>
<table border=1 cellpadding=2 cellspacing=0>
<tr>
<th>Operation</th>
<th>Context</th>
<th><c>()</c> Capturing<br>Groups</th>
<th>Return Value on Match<br>(and notes on behavior)</th>
<th>Return Value on Failure</th>
<th width="250">Example</th>
</tr>
<tr>
<td><c>m//</c></td>
<td>scalar</td>
<td>-</td>
<td>true</td>
<td>false</td>
<td width="250">
<c>
my $x = "foobar"=~/[aeiou]/; # => $x is true
my $y = "foobar"=~/[xyz]/; # => $y is false
</c>
</td>
</tr>
<tr>
<td><c>m//g</c></td>
<td>scalar</td>
<td>-</td>
<td>true<br>
(each execution of <c>m//g</c> finds the <i>next</i> match,<br>
see [doc://perlretut#Global-matching|"Global matching" in perlretut])</td>
<td>false if there is no further match</td>
<td width="250">
<c>
my $str = "foobar";
my $x = $str=~/[aeiou]/g;
# matches first "o" => $x is true, pos($str) is 2
$x = $str=~/[aeiou]/g;
# matches second "o" => $x is true, pos($str) is 3
$x = $str=~/[aeiou]/g;
# matches "a" => $x is true, pos($str) is 5
$x = $str=~/[aeiou]/g;
# no more matches => $x is false, pos($str) is undef
</c>
</td>
</tr>
<tr>
<td><c>m//</c></td>
<td>list</td>
<td>no</td>
<td>the list <c>(1)</c></td>
<td>the empty list <c>()</c></td>
<td width="250">
<c>
my ($x) = "foobar"=~/[aeiou]/; # => $x is 1
</c>
</td>
</tr>
<tr>
<td><c>m//g</c></td>
<td>list</td>
<td>no</td>
<td>a list of all the matched strings, as if there were parentheses around the whole pattern</td>
<td>the empty list <c>()</c></td>
<td width="250">
<c>
my ($x,$y,$z) = "foobar"=~/[aeiou]/g;
# => $x is "o", $y is "o", $z is "a"
</c>
</td>
</tr>
<tr>
<td><c>m//</c></td>
<td>list</td>
<td>yes</td>
<td>a list consisting of the subexpressions matched by the parentheses in the pattern, that is, (<c>$1</c>, <c>$2</c>, <c>$3</c>...)</td>
<td>the empty list <c>()</c></td>
<td width="250">
<c>
my ($x,$y) = "foobar"=~/([aeiou])(.)/;
# => $x is "o", $y is "o"
</c>
</td>
</tr>
<tr>
<td><c>m//g</c></td>
<td>list</td>
<td>yes</td>
<td>a list of the substrings matched by any capturing parentheses in the regular expression, that is, (<c>$1</c>, <c>$2</c>...) repeated for each match</td>
<td>the empty list <c>()</c></td>
<td width="250">
<c>
my ($w,$x,$y,$z) = "foobar"=~/([aeiou])(.)/g;
# => $w is "o", $x is "o", $y is "a", $z is "r"
</c>
</td>
</tr>
<tr>
<td><c>s///</c></td>
<td>-</td>
<td>-</td>
<td>the number of substitutions made</td>
<td>false</td>
<td width="250">
<c>
my $x = "foobar";
my $y = $x=~s/[aeiou]/x/g; # => $y is 3
</c>
</td>
</tr>
<tr>
<td><c>s///r</c></td>
<td>-</td>
<td>-</td>
<td>a copy of the original string with substitution(s) applied<br>
<i>(available since Perl 5.14)</i></td>
<td>the original string</td>
<td width="250">
<c>
my $x = "foobar"=~s/[aeiou]/x/gr;
# => $x is "fxxbxr"
</c>
</td>
</tr>
</table>
<p>In this table, "true" and "false" refer to Perl's notion of [id://11104607]. <b>Remember</b> not to rely on any of the capture variables like <c>$1</c>, <c>$2</c>, etc. unless the match succeeds!</p>
<p>In <c>my $foo = "bar"=~/a/;</c>, the right-hand side of the assignment (<c>"bar"=~/a/</c>) is in scalar context. In <c>my ($foo) = "bar"=~/a/;</c> or <c>my @foo = "bar"=~/a/;</c>, the right-hand side is in list context. That's why, in your example, you need those parens in <c>($value)</c>: because you want the matching operation to return the contents of the capture group.</p>
<p>Note that your expressions can be slightly simplified, not all the parens you showed are needed:</p>
<c>
my ($value) = $row =~ /.*,(.*)/;
# and
$row =~ s/,[^,]*$//;
</c>
<p>A few additional comments on your code:</p>
<ul>
<li><c>($row =~ s/,[^,]*$//); # gets substring before the last comma</c> - this comment isn't quite right or at least potentially misleading, since it <i>deletes</i> the string <del>before</del> <ins>after and including</ins> the last comma.</li>
<li><c>/.*,(.*)/</c> matches any comma anywhere in the string, for simple input strings it may behave correctly, but I'd strongly recommend coding more defensively and writing it like your second expression: <c>my ($value) = $row=~/,([^,]*)$/;</c> - the <c>$</c> anchor makes sure that the regex only matches the last comma and what follows it (unless you use the <c>/m</c> modifier, since it changes the meaning of <c>$</c>).</li>
<li>While the use of [doc://Scalar::Util]'s <c>looks_like_number</c> is often a good idea, note that if you don't mind being a little more restrictive, [mod://Regexp::Common] (or a hand-written regex) would allow you to combine the two regular expressions:
<c>
use Regexp::Common qw/number/;
my $row = "a,b,c,d,15";
if ( $row=~s/,($RE{num}{real})$// ) {
print "matched <$1>\n";
}
print "row is now <$row>\n";
__END__
matched <15>
row is now <a,b,c,d>
</c>
</li>
<li>If this is a CSV file, consider using [mod://Text::CSV] (also install [mod://Text::CSV_XS] for speed)</li>
</ul>
<p><small><i>Update:</i> Added <c>s///r</c> to the table and added a few more doc links. A few other edits and updates. <i>2019-02-16:</i> Added "Return Value on Failure" column to table, and a few other small updates. <i>2019-08-17:</i> Updated the link to "Truth and Falsehood".</small></p>
1215361
1215361