Search code examples
shdouble-quotessingle-quotes

Shell script to build CLI args for a PERL script


I have a Jenkins job, triggered as a parameterized build. It accepts an optional String parameter (HOSTNAMES) that can be a comma separated list of hostnames.

I need to pass this comma separated list of hostnames as a command line argument to a PERL script (within Execute shell build step).

Here is how I process the input parameter and construct the command line argument within the execute shell build step:

cmd_options=''
echo hostnames is $HOSTNAMES
if [ "$HOSTNAMES" != "" ]
  then
  cmd_options+=" --hostnames \"$HOSTNAMES\""
fi
perl myscript.pl $cmd_options

In the console output of the build though, I see the argument being passed incorrectly. Here is the console output:

+ cmd_options=
+ echo hostnames is host1, host2
hostnames is host1, host2
+ '[' 'host1, host2' '!=' '' ']'
+ cmd_options+=' --hostnames "host1, host2"'
+ perl myscript.pl --hostnames '"host1,' 'host2"'

I want myscript.pl to be called this way:

perl myscript.pl --hostnames "host1, host2"

I have tried various ways of manipulating $cmd_options using single quotes and double quotes, but have been unsuccessful so far in getting it right. Any pointers at where I am going wrong?


Solution

  • When you build a command, delay the interpolation and use eval to execute it.

    HOSTNAMES='host1, host2'
    
    cmd_options=''
    if [ "$HOSTNAMES" != "" ]; then
       cmd_options+='--hostnames "$HOSTNAMES"'
    fi
    
    eval "prog $cmd_options"
    

    A better solution is to use an array.

    HOSTNAMES='host1, host2'
    
    cmd_options=()
    if [ "$HOSTNAMES" != "" ]; then
       cmd_options+=(--hostnames "$HOSTNAMES")
    fi
    
    prog "${cmd_options[@]}"
    

    If prog is the following program:

    #!/usr/bin/perl
    use feature qw( say );
    say 0+@ARGV; say for @ARGV
    

    Both snippets output the following:

    2
    --hostnames
    host1, host2