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.
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
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.
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")'
map is an array. Thanks for clarification.map is not an array. In list context, the return value from map is a list. In scalar context, it is the number of elements in that list. Lists are not arrays.