Marcus
Marcus

Reputation: 5245

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.

Upvotes: 1

Views: 108

Answers (2)

choroba
choroba

Reputation: 241988

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 }'

Upvotes: 5

anubhava
anubhava

Reputation: 785531

You can use $_ to add up all of the input:

echo $'1\n2\n3' | perl -ne '$tot += $_; END { print $tot . "\n" }'

6

Or else, you can use -a (autosplit) option to split input into fields:

echo $'1\n2\n3' | perl -ane '$tot += $F[0]; END { print $tot . "\n" }'

6

Upvotes: 1

Related Questions