Shell – Quoting and escaping

quotingshell-script

I have a shell script, the arguments of which are collected in quote as a single argument and passed to a perl script.

/usr/local/API/check_api.sh "-D x.x.x.x -C Test_Internal_Cluster -u user -p pass  -i 300 -l runtime -s list"

which result to

/usr/bin/perl /usr/local/check_api.pl -D x.x.x.x -C Test_Internal_Cluster -u user -p pass -i 300 -l runtime -s list

I want to give an argument like this:

"Test Internal Cluster"

to the perl script.

When I am using

"Test\ Internal\ Cluster"

as the argument to the shell script its parsing as

Test Internal Cluster

to the perl script, but I want that to be in double quotes.

If I am using this:

""\"Test Internal Cluster\"

It converting to:

'"Test' Internal 'Cluster"'

This seems simple but not able to use proper quoting and escaping to achieve.

The shell script is:

#!/bin/bash -xv

Perl=/usr/bin/perl
Api=/usr/local/API/check_api.pl

if [ $# -gt 0 ]; then
  if [ -x $Api ]
   then
        output=$($Perl $Api $1)
        exitstatus=$?
        F1=$(echo $output | awk -F':' '{print $1}')
        F2=$(echo $output | awk -F':' '{print $2}' | awk -F'|' '{print $1}')
        F3=$(echo $output | awk -F':' '{print $2}' | awk -F'|' '{print $2}')
        echo " $F1: $F3 | $F2"
  else
        echo "check_api.pl not found"
 fi
 exit $exitstatus
else
    echo "Usage : $0 '-D <DC> -C <Cluster> -u <userbame> -p <password> -i <interval> -l <command>  -s <subcommand>'"
fi

Here you can see the whole argument passed to the shell script is collected to $1 and passed to the check_api perl script.

The issue is happening with cluster name with space (passed to -C).

And the whole argument passed to the shell script should be in single/double quotes.

I haven't quoted the variable $1 because the perlscript is not accepting the whole argument as a single as below which I found in debug mode – where the whole argument is quoted if $1 is quoted.

/usr/bin/perl /usr/local/check_api.pl '-D x.x.x.x -C Test_Internal_Cluster -u user -p pass  -i 300 -l runtime -s list'

and throws error as incorrect usage

But without quoting the $1 the argument passed to perl script works like this and which gives me the result:

/usr/bin/perl /usr/local/check_api.pl -D x.x.x.x -C Test_Internal_Cluster -u user -p pass -i 300 -l runtime -s list

But I am failed with a cluster with space in its name.

In case of a space in cluster name if I am running in the command line directly(not from shell script) it works fine without any issue:

/usr/bin/perl /usr/local/check_api.pl -D x.x.x.x -C "Test Internal Cluster" -u user -p pass -i 300 -l runtime -s list

which I wanted to achieve from shell script.

Best Answer

You should use like this:

"\"Test Internal Cluster\""

or wrap it in single quote:

'"Test Internal Cluster"'

Test:

#!/bin/bash

echo $1

Output:

% bash test.sh "\"Test Internal Cluster\""
"Test Internal Cluster"

Update

The problem here is becasue you call perl with $1, $1 contains white space, so perl will see it as three separate arguments.

To prevent this, you should wrap $1 in double quotes "$1".

Another note is you should handle $1 argument in perl script, because if $1 contains any special characters, it will cause some bugs in perl program. you can use quotemeta($ARGV[0]).

Note

I think you shoul not pass all argument as a string to shell script. You should pass them as normal, except cluster name, you still have to wrap it as string. Then pass them to perl script by "$@" instead of $1.

Related Question