Printing an array within double quotes

后端 未结 5 1733
栀梦
栀梦 2020-12-18 08:17
my @a = (1,2,3,4,5);

print @a;      #output: 12345

print \"\\n\";

print \"@a\";    #output: 1 2 3 4 5

Printing an array by putting its name with

相关标签:
5条回答
  • 2020-12-18 08:40

    When Perl sees an array in an interpolated string, it rewrites it using join:

    print "@array";
    

    becomes

    print join($" => @array);
    

    by default, the value of $" is equal to a single space.

    You can configure this behavior by localizing a change to $"

    print "@array";     # '1 2 3 4 5'
    {
        local $" = '';  # "
        print "@array"; # '12345'
    }
    print "@array";     # '1 2 3 4 5' 
    

    You can see how Perl rewrites your interpolated strings using the -q option of the core B::Deparse module:

    $ perl -MO=Deparse,-q -e 'print "@array"'
    print join($", @array);
    -e syntax OK
    
    0 讨论(0)
  • 2020-12-18 08:47

    Array in double quotes

    The “Array Interpolation” section of the perldata documentation explains how the intercalated spaces in the value of "@a" get there:

    Arrays and slices are interpolated into double-quoted strings by joining the elements with the delimiter specified in the $" variable ($LIST_SEPARATOR if use English; is specified), space by default. The following are equivalent:

    $temp = join($", @ARGV);  # " for benefit of StackOverflow hiliter
    system "echo $temp";
    system "echo @ARGV";
    

    This means that print "@a" passes a single scalar argument to print. In contrast, print @a in your example passes five.

    Printing multiple values

    The perlfunc documentation on print explains what print with a list of arguments.

    print LIST

    … The current value of $, (if any) is printed between each LIST item.

    The perlvar documentation on $, is

    Handle->output_field_separator( EXPR )
    $OUTPUT_FIELD_SEPARATOR
    $OFS
    $,

    The output field separator for the print operator. If defined, this value is printed between each of print's arguments. Default is undef.

    Mnemonic: what is printed when there is a , in your print statement.

    Because $, defaults to the undefined value, you're seeing print output its arguments with no separator. In explicit terms, the code from your question is equivalent to

    print join("", @a);
    

    Why?

    The difference in behavior isn't a special case for print. Arrays interpolate into all double-quoted strings as described above. A quick survey of Google code-search hits for print "@... seems to indicate that a frequent use for print "@foo" is debugging output, as in

    sub foo {
      print "args = @_\n" if $debug;
      ...;
    }
    

    A handy trick that Mark Dominus uses to provide visible separators for lists whose values may contain spaces is

    sub foo {
      if ($debug) {
        local $" = "][";
        print "args = [@_];  # e.g., [foo][1][3.14159]
      }
      ...;
    }
    

    Say @a contains lines of output such as

    @a = map "  - $_\n", @error_messages;
    print @a;
    

    Inserting implicit spaces between the values would hose my carefully constructed formatting:

      - sneaky-sneaky, sir
       - the hideousness of that foot will haunt my dreams forever
        - why would you do that?!

    Perl tries hard to do what we mean, even when we're inconsistent in the demands we make.

    0 讨论(0)
  • 2020-12-18 08:53

    Even better question: Why doesn't it print something like array{0x1232ef}. Print is suppose to print a string output and @a isn't a scalar.

    Heck, even better: This is a scalar context, so why not print 5 which is the number of elements in the array. This is how:

    print scalar @a;
    

    would print.

    Instead, the print command is taking some liberties to try to do what you intended and not what you said you want.

    Let's take a look at this little program:

    @a = qw(a b c d e);
    
    print "@a";         #prints "a b c d e"
    print "\n";
    
    print @a;           #prints "abcde"
    print "\n";
    
    print @a . "\n";    #prints "5"
    
    print scalar @a;    #prints "5"
    

    Notice that print @a prints abcde, but if I add a \n on the end, it then prints @a in a scalar context.

    Take a look at the Perldoc on print (try the command perldoc -f print. On most systems, the entire Perl documentation is available via perldoc)

    * print LIST
    * print
    
    Prints a string or a list of strings. Returns true if successful[...]
    

    Ah! If given a list, it'll print a list of strings.

    The current value of $, (if any) is printed between each LIST item. The current value of $\ (if any) is printed after the entire LIST has been printed. Because print takes a LIST, anything in the LIST is evaluated in list context, including any subroutines whose return lists you pass to print.

    Let's try a new program:

    @a = qw(a b c d e);
    
    $, = "--";
    print "@a";         #prints "a b c d e"
    print "\n";
    
    print @a;           #prints "a--b--c--d--e"
    print "\n";
    
    print @a . "\n";    #prints "5"
    
    print scalar @a;    #prints "5"
    

    Hmmm... The $, added the double dashes between the list elements, but it didn't affect the @a in quotes. And, if $, is mentioned in the perldoc, why is everyone prattling about $"?

    Let's take a look at perldoc perlvar

    * $LIST_SEPARATOR
    * $"
    
    When an array or an array slice is interpolated into a double-quoted string or a
    similar context such as /.../ , its elements are separated by this value. Default
    is a space. For example, this:
    
    print "The array is: @array\n";
    
    is equivalent to this:
    
    print "The array is: " . join($", @array) . "\n";
    
    Mnemonic: works in double-quoted context.
    

    So, that explains everything!

    The default of $" is a single space, and the default of $, is null. That's why we got what we got!

    One more program...

    @a = qw(a b c d e);
    
    $, = "--";
    $" = "++";
    print "@a";         #prints "a++b++c++d++e"
    print "\n";
    
    print @a;           #prints "a--b--c--d--e"
    print "\n";
    
    print @a . "\n";    #prints "5"
    print scalar @a;    #prints "5"
    
    0 讨论(0)
  • 2020-12-18 08:57

    When an array is interpolated in a string, the assumption is you may want to be able to visually distinguish elements; when you print a list, the assumption is you just want that data output contiguously. Both are configurable; $, (default '') is inserted between elements of a list being printed, while $" (default ' ') is inserted between elements of an array interpolated into a string.

    0 讨论(0)
  • 2020-12-18 08:58

    In the first instance, you are passing a list of arguments to print, and each is printed in turn.

    In the second, you are interpolating an array into a string, and then printing the result. When an array in interpolated in a string, the values are separated by $", which defaults to .

    0 讨论(0)
提交回复
热议问题