Getopt::Long getting a string with spaces into a variable

坚强是说给别人听的谎言 提交于 2019-12-01 11:20:38

You need to either put quotes around the argument:

./script.pl --string="blah blah blah blah yup" --another-opt

or escape the spaces:

./script.pl --string=blah\ blah\ blah\ blah\ yup --another-opt

This is really a reply to MaxMackie's question on Ernest's answer, but it's too long, so here goes:

Your script never sees the quotes, only the shell that is passing the arguments. When you call a script (or program), what is happening on a lower level is that the command is called with several arguments in an array. The shell normally splits arguments up based on whitespace. What your program sees right now is:

[0]./script.pl
[1]--string=blah
[2]blah
[3]blah
[4]blah
[5]yup
[6]--another-opt

Putting quotes around the string or escaping it results in in this:

[0]./script.pl
[1]--string=blah blah blah blah yup
[2]--another-opt

Shells (bash in particular, others I'm sure) allows interspersing quotes without spaces as much as you like. ls -"l""h" is the same as ls -lh, hence you an do "--string=blah blah" or --string="blah blah". The parsing of the individual arguments with getopt that lets you put them out of order and use --long-name or -l happens after everything is turned into an array item and passed to the program. The shell has nothing to do with that.

While I certainly agree that you should escape the arguments, if like me you have situation where you don't easily have control over the input then it is actually possible to do this with Getopt::Long.

Example: [https://www.jdoodle.com/a/oHG]

use strict;
use Getopt::Long qw(GetOptions);


my @spaces_string;

GetOptions('test=s{1,}' => \@spaces_string);
printf "String is: '%s'\n" ,join " ",@spaces_string;

You are defining your option as having 1 or more values, assign it to an array and then join it back into a string.

This is explained quite well under the 'Options with multiple values' section of the documentation: http://perldoc.perl.org/Getopt/Long.html#Options-with-multiple-values

Now riddle me this... in the following scenario, I want to generate a quoted command-line argument via a shell command which then gets passed to a Perl script, like this:

script.pl `echo --string \"blah blah yup\"`

Trouble is, GetOptions ("string=s" => \$string) sets string's value to

"blah

containing the initial double-quote character and breaking at the first whitespace. The echo command by itself outputs the parameter with a quoted string that looks peachy:

--string "blah blah yup"

and if I call script.pl --string "blah blah yup" without the echo, the whitespace containing string gets set in the Perl script as expected.

I thought that maybe the backticks were the issue, but the same results ensue with these variants:

script.pl $(echo --string \"blah blah yup\")
script.pl $(echo "--string \"blah blah yup\"")
script.pl $(echo --string \"blah\ blah\ yup\")
script.pl $(echo '--string \"blah blah yup\"')

though that last example leads to string=\"blah (containing the initial backslash and double quote character).

Seems like the output returned from a shell command's STDOUT is not being handled the same way by Perl's argument parsing machinery as a string that is typed into the command-line. This apparent lack of string fungibility is somewhat surprising, but probably owing to some aspect of bash I don't understand. (Btw, I tested this with Perl 5.24 on Darwin and 5.16 on Linux)

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!