0

I see that similar questions were answered before but my scenario is a little bit different:

  • I need to store a command in a variable in order to I can log it before running
  • the command contains variables that can contain space between the words
  • the result of the execution must assign to a new variable

This is the command that works properly from the terminal:

java -jar ${ORACLE_HOME}/bin/sql-command-line-tool/sql-runner-0.2.2-with-dependencies.jar -v -U ${DB_USERNAME} -P ${DB_PASSWORD} -j jdbc:oracle:thin:@${DB_HOST}:${DB_PORT}/${DB_NAME} "select 1 from dual"

Variables:

  • DB_HOST=oracle-db
  • DB_PORT=1521
  • DB_NAME=ORCLPDB1.localdomain
  • DB_USERNAME="SYS as SYSDBA"
  • DB_PASSWORD=Oradoc_db1

Test:

$ echo $DB_USERNAME
"SYS as SYSDBA"

This is how I want to use but this does not work:

echo "checking whether database server is up and running..."
_COMMAND="java -jar ${ORACLE_HOME}/bin/sql-command-line-tool/sql-runner-0.2.2-with-dependencies.jar -v -U ${DB_USERNAME} -P ${DB_PASSWORD} -j jdbc:oracle:thin:@${DB_HOST}:${DB_PORT}/${DB_NAME} \"select 1 from dual\""
echo "command: $_COMMAND"
_RESULT=$($_COMMAND)
_SHOW_MESSAGE=true

while [[ ${_RESULT} ]]
do
    if [ $_SHOW_MESSAGE = "true" ]; then echo "the database server is not running yet, waiting..."; fi
    if [ $VERBOSE = "false" ]; then _SHOW_MESSAGE="false"; fi
    sleep 0.5
    _JSON=$($_COMMAND)
done
echo "database server is up and running"

Error:

Unmatched arguments from index 4: 'SYSDBA"', '"select', '1', 'from', 'dual"'

The jar I use is available from here.

I have tried to use single and double quotes in different ways, tried to use eval but non of them worked properly.

What I missed?

λuser
  • 893
  • 8
  • 14
zappee
  • 20,148
  • 14
  • 73
  • 129
  • While executing the `_COMMAND`, you'll need to wrap the command output in quotes: `_RESULT="$($_COMMAND)"` if those can have newlines etc – 0stone0 Feb 22 '21 at 16:13
  • Also, try pasting the script on [https://www.shellcheck.net/](https://www.shellcheck.net/) to check for default bash errors: `_RESULT=$($_COMMAND) ^-- SC2090: Quotes/backslashes in this variable will not be respected.` – 0stone0 Feb 22 '21 at 16:14
  • @0stone0 unfortunately extra quotas around `_COMMAND` did not help. – zappee Feb 22 '21 at 16:22
  • It's not just the quotes around `_COMMAND`, but also on those other assignments where the might be quotes/newlines in the response. – 0stone0 Feb 22 '21 at 16:23
  • 1
    [I'm trying to put a command in a variable, but the complex cases always fail!](http://mywiki.wooledge.org/BashFAQ/050) – glenn jackman Feb 22 '21 at 16:31
  • The link given by glenn above explains _why_ the `$_COMMAND` approach generally is unworkable; it's very much worth reading. Using a function or array instead of a string to store commands is very much the Right Thing. – Charles Duffy Feb 22 '21 at 16:46

2 Answers2

2

There are some general issues I'll try to address.


  1. There's no Bash Shebang

  2. While creating the command, your username contains a space (DB_USERNAME="SYS as SYSDBA") therefore you'll need to wrap those in quotes;

    COMMAND="... -v -U '${DB_USERNAME}' -P ${DB_PASSWORD} ...
    
  3. When to wrap quotes around a shell variable?;

    while [[ "${_RESULT}" ]]
    
    _RESULT="$($_COMMAND)"
    
    _JSON="$($_COMMAND)"
    
    if [ "$VERBOSE" = "false" ]
    

Using a took like https://www.shellcheck.net/ will help finding those bash errors

0stone0
  • 34,288
  • 4
  • 39
  • 64
-1

In general it is not a good practice to define a bash command as a variable. I would recommend:

  1. Create an alias
  2. Create a bash function
  3. Create a bash script and call it with either source or bash appropriately.

Bash function example

_COMMAND() {
    # Argument parsing with default values/error statements
    if [ -z ${ORACLE_HOME+x} ]
    then 
        echo "ERROR: ORACLE_HOME not defined"
        return 0
    fi
    DB_HOST=${1:-"oracle-db"}
    DB_PORT=${2:-1521}
    DB_NAME=${3:-"ORCLPDB1.localdomain"}
    DB_USERNAME=${4:-"SYS as SYSDBA"}
    DB_PASSWORD=${5:-"Oradoc_db1"}
    # Execute command
    java -jar "${ORACLE_HOME}/bin/sql-command-line-tool/sql-runner-0.2.2-with-dependencies.jar" -v -U "${DB_USERNAME}" -P "${DB_PASSWORD}" -j jdbc:oracle:thin:@"${DB_HOST}":${DB_PORT}/"${DB_NAME}" "select 1 from dual"
}

After defining this function you can capture the result of the call with:

_RESULT="$(_COMMAND)"
  • 1
    Please don't answer duplicative questions. See the section _Answer Well-Asked Questions_ in [How to Answer](https://stackoverflow.com/help/how-to-answer). Such questions should be closed as duplicates; and then, if the canonical instances aren't sufficiently well-answered, new answers can/should be added directly on them. – Charles Duffy Feb 22 '21 at 16:47