2

Unable to print same argument of $1

    #!/bin/bash
    if [[ "$1" =~ ^((-{1,2})([Hh]$|[Hh][Ee][Ll][Pp])|)$ ]]; then
            display_help; exit 1
    else
            while [[ $# -gt 0 ]]; do
            opt="$1"
            shift;
            current_arg="$1"
            case "$opt" in
                    "run_command"   ) RUN_COMMAND="$1"; shift;;
                    "cmd1"          ) CMD1="$1"; shift;;
                    *                   ) echo "ERROR: Invalid option: \""$opt"\"" >&2
                          exit 1;;
            esac
            done
    fi

    if [[ "$RUN_COMMAND" == "Custom" ]];then
            export command1=`echo $CMD1`
            echo $command1
    else
            echo "Invalid arguments"
    fi

Result output

  ./test_non.sh run_command Custom cmd1 "date|awk '{print \\$1}'"
    date|awk '{print \}'
2
  • 1
    Please edit your question and give us the simplest possible version of your script that reproduces the error. We need something we can copy and run on our own machines. – terdon Nov 15 '19 at 10:56
  • How are you setting $opt, for example? – terdon Nov 15 '19 at 11:02
0

You should use

./script run_command Custom cmd1 "date|awk '{print \\$1}'"

Why? I don't really know the reason of that double \, but probably it need to escape the special character $ AND the argument number too (one \ for $ and 1)

Here is some results :

  • good one :

    damadam@Pc:~$ export command1=`echo "date|awk '{print \\$1}'"`
    damadam@Pc:~$ echo $command1
    date|awk '{print $1}'
    
  • tests :

    damadam@Pc:~$ export command1=`echo "date|awk '{print \$\1}'"`
    damadam@Pc:~$ echo $command1
    date|awk '{print $\1}'
    
    damadam@Pc:~$ export command1=`echo "date|awk '{print $\1}'"`
    damadam@Pc:~$ echo $command1
    date|awk '{print $\1}'
    
  • OP test :

    damadam@Pc:~$ export command1=`echo "date|awk '{print \$1}'"`
    damadam@Pc:~$ echo $command1
    date|awk '{print }'
    

Edit 1: with the sample script code given by OP (I named it test.sh to test it personnally), just need a single \ to escape the $1 argument

damadam@Pc:~$ ./test.sh run_command Custom cmd1 "date|awk '{print \$1}'"
date|awk '{print $1}'
1
  • 1
    You only needed the two \\ because you were using two levels: first, the process substitution (var1=`echo var2` ), which wasn't needed anyway since you could just do var1=var2. The process substitution runs in a separate subshell, so you needed one escape to pass the $1 correctly to that. Then, the whole thing was in double quotes, so you needed the second escape so that $1 wasn't expanded in the double quotes before even being passed to the first subshell. – terdon Nov 15 '19 at 11:18
3

First of all, when you run this:

./script run_command Custom cmd1 "date|awk '{print $1}'"

Because your command is in double quotes, that means it will be expanded by the shell (bash) before calling your script. You can always test these things using set -x:

$ set -x
$ ./script run_command Custom cmd1 "date|awk '{print $1}'"
+ ./script run_command Custom cmd1 'date|awk '\''{print $1}'\'''
date|awk '{print $1}'

The line starting with + shows you the command actually run. As you can see, the $1 has disappeared because $ indicates a shell variable and, since you have everything in double quotes, that is passed to the shell which tries to expand it. Since $1 isn't set, it expands to nothing. Compare it to what happens if you use a variable that is set:

$ foo="bar"
$ ./script run_command Custom cmd1 "date|awk '{print $foo}'"
+ ./script run_command Custom cmd1 'date|awk '\''{print bar}'\'''
date|awk '{print bar}'

As you can see, the $foo in your awk command is expanded to bar before being passed to ./script. So, you need to escape the $1:

$ ./script run_command Custom cmd1 "date|awk '{print \$1}'"
+ ./script run_command Custom cmd1 'date|awk '\''{print $1}'\'''
date|awk '{print $1}'

I also don't understand what this is supposed to be doing:

if [[ "$RUN_COMMAND" == "Custom" ]];then
  export command1=`echo $CMD1`
  echo $command1
else

You don't need export at all, and you don't need to echo one variable to set it as the value of another. All you need there is:

if [[ "$RUN_COMMAND" == "Custom" ]];then
  command1=$CMD1

In fact, you don't need $CMD1 at all. Just set $command1 from the beginning. Here's a slightly improved version of your script:

#!/bin/bash

## dummy function since you didn't include yours
display_help(){
  echo "help"
}

if [[ "$1" =~ ^((-{1,2})([Hh]$|[Hh][Ee][Ll][Pp])|)$ ]]; then
  display_help
  exit 1
else
  while [[ $# -gt 0 ]]; do
    opt="$1"
    shift;
    current_arg="$1"
    case "$opt" in
      "run_command")
        RUN_COMMAND="$1"
        shift
        ;;
      "cmd1")
        command1="$1"
        shift
        ;;
      *)
        echo "ERROR: Invalid option: '$opt'" >&2
        exit 1
        ;;
    esac
  done
fi

if [[ "$RUN_COMMAND" == "Custom" ]];then
  echo "$command1"
else
  echo "Invalid arguments"
fi

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.