Reputation: 3107
I need to concate map
result with a string.
perl -le 'print (map { (q(a)..q(z))[rand(26)] } 1..3) . "123"'
Expected 3 random symbols and 123
. But there is no 123
just 3 random symbols.
In general, I need to add a variable there.
Upvotes: 1
Views: 132
Reputation: 385764
With warnings:
print (...) interpreted as function at -e line 1.
Useless use of concatenation (.) or string in void context at -e line 1.
This is because your code is of the following form:
print(...) . "123"
Solutions:
perl -le'print( map( { (q(a)..q(z))[rand(26)] } 1..3 ) . "123" )' # Fully parenthesized
perl -le'print map( { (q(a)..q(z))[rand(26)] } 1..3 ) . "123"' # Opt parens dropped
perl -le'print( ( map { (q(a)..q(z))[rand(26)] } 1..3 ) . "123" )'
perl -le'print +( map { (q(a)..q(z))[rand(26)] } 1..3 ) . "123"' # "Disambiguated"
Except those aren't right either. While they fix the problem you asked about, they reveal a second problem. They invariably print 3123
because map
in scalar context returns the number of scalars it would otherwise return in list context.
Solutions:
perl -le'print( map( { (q(a)..q(z))[rand(26)] } 1..3 ), "123" )' # . => ,
perl -le'print map( { (q(a)..q(z))[rand(26)] } 1..3 ), "123"' # . => ,
perl -le'print( ( map { (q(a)..q(z))[rand(26)] } 1..3 ), "123" )' # . => ,
perl -le'print +( map { (q(a)..q(z))[rand(26)] } 1..3 ), "123"' # . => ,
perl -le'print join "", ( map { (q(a)..q(z))[rand(26)] } 1..3 ), "123"' # join
Upvotes: 3
Reputation: 69244
There are a couple of interesting things going on here. First let's ask Perl to help up track down any problems by turning on warnings.
$ perl -Mwarnings -le 'print (map { (q(a)..q(z))[rand(26)] } 1..3) . "123"'
print (...) interpreted as function at -e line 1.
Useless use of concatenation (.) or string in void context at -e line 1.
lfy
Two warnings there. Let's look at both of them.
print (...) interpreted as function
If the first non-whitespace character following print
(or any other list operator) is a opening parenthesis, then Perl assumes that you want to call print
as a function and it will look for the balancing closing parenthesis to end the list of arguments to print
.
Useless use of concatenation (.) or string in void context
Because the print
call is assumed to end with the closing parenthesis, the . "123"
isn't doing anything useful. And is therefore ignored.
The standard way to tell Perl that an opening parenthesis isn't marking a function call is to use a +
.
$ perl -Mwarnings -le 'print +(map { (q(a)..q(z))[rand(26)] } 1..3) . "123"'
3123
Well, we lost the warnings. But we got '3' where we were hoping to see three symbols. What we have here now is basically this:
print +(map ...) . "123";
Because of the concatenation, map
is being called in scalar context. And in scalar context, map
no longer returns a list of values, but the size of that list (an integer - 3 in this case).
The fix for that is to replace the .
with a comma, so map
is called in list context.
$ perl -Mwarnings -le 'print +(map { (q(a)..q(z))[rand(26)] } 1..3), "123"'
ntg123
So you were being burnt by a) the parentheses not doing what you wanted them to do and b) map
being called in scalar context.
Upvotes: 2
Reputation: 91385
Enclose the whole line to be printed inside parenthesis and use a comma as separator:
perl -le 'print ( (map { (q(a)..q(z))[rand(26)] } 1..3) , "123")'
Upvotes: 0
Reputation: 2005
perl -le 'print join("",map { (q(a)..q(z))[rand(26)] } 1..3) . "123"'
Upvotes: 0