Search code examples
regexperltext-processingcapturing-group

Why Perl regex capturing groups behave differently between `print` and arithmentic operations?


In Perl (v5.30.0), regex are evaluated as the captures, when used as parameters of print():

# Simplified example; the real case has more text, and the capture covers only part of it.

echo $'1\n2\n3' | perl -ne 'print /(.)/'
# 123

This is great for text extraction. I'd like to exploit the same convenience for arithmetic operations, but this doesn't work as expected:

# Attempt to compute a sum of the int value of the captures
#
echo $'1\n2\n3' | perl -ne '$tot += /(.)/; END { print $tot }'
# 3

# Attempt to print twice the int value of each capture
#
echo $'1\n2\n3' | perl -ne 'print(/(.)/ * 2)'
# 222

Using the capture variables work:

echo $'1\n2\n3' | perl -ne 'if (/(.)/) { $tot += $1 }; END { print $tot }'
# 6

However, I was curious why this happens, and if it's possible in any way to use the previous, more compact, form, in order to perform arithmetic operations on captured values.


Solution

  • That's because m// returns 1 for success in scalar context (see perlop). You can enforce list context to return the matched part:

    echo $'1\n2\n3' | perl -ne '$tot += (/(.)/)[0]; END { print $tot }'