Christian Watts
Christian Watts

Reputation: 75

Bash read line from variables

Hi & thanks in advance.

I'm trying to update a column(version) on an MySQL table from a Bash script.

I've populated a variable with the version numbers, but it fails after applying the first version in the list.

CODE:

UP_VER=`seq ${DB_VER} ${LT_VER} | sed '1d'`
UP_DB=`echo "UPDATE client SET current_db_vers='${UP_VER}' WHERE client_name='${CLIENT}'" | ${MYSQL_ID}`
while read -r line
 do
  ${UP_DB}
  if [[ "${OUT}" -eq "0" ]]; then
    echo "Database upgraded.."
  else
    echo "Failed to upgrade.."
    exit 1
  fi
done < "${UP_VER}"

Thanks

Hopefully solved... My $UP_VER is in a a row not a column.

Upvotes: 0

Views: 237

Answers (2)

Gordon Davisson
Gordon Davisson

Reputation: 125798

You're misunderstanding what several shell constructs do:

var=`command`  # This executes the command immediately, and stores
               # its result (NOT the command itself) in the variable

... < "${UP_VER}"  # Treats the contents of $UP_VER as a filename, and tries
                   # to use that file as input

if [[ "${OUT}" -eq "0" ]]; then  # $OUT is not defined anywhere

... current_db_vers='${UP_VER}' ...  # this sets current_db_vers to the entire
                                     # list of versions at once

Also, in the shell it's best to use lowercase (or mixed-case) variable names to avoid conflicts with the variables that have special meanings (which are all uppercase).

To fix the first problem, my recommendation is don't try to store shell commands in variables, it doesn't work right. (See BashFAQ #50: I'm trying to put a command in a variable, but the complex cases always fail!.) Either use a function, or just write the command directly where it's going to be executed. In this case I'd vote for just putting it directly where it's going to be executed. BTW, you're making the same mistake with ${MYSQL_ID}, so I'd recommend fixing that as well.

For the second problem, you can use <<< "${UP_VER}" to feed a variable's contents as input (although this is a bashism, and not available in generic posix shells). But in this case I'd just use a for loop:

for ((ver=db_ver+1; ver<=lt_ver; ver++)); do

For the third problem, the simplest way to test the success of a command is to put it directly in the if:

if somecommand; then
     echo "Database upgraded.."
else # ... etc

So, here's my take at a rewrite:

mysql_id() {
    # appropriate function definition goes here...
}

for ((ver=db_ver+1; ver<=lt_ver; ver++)); do
  if echo "UPDATE client SET current_db_vers='${ver}' WHERE client_name='${client}'" | mysql_id; then
    echo "Database upgraded.."
  else
    echo "Failed to upgrade.."
    exit 1
  fi
done

... but I'm not sure I understand what it's supposed to do. It seems to be updating current_db_vers one number at a time until it reaches $ver_lt... but why not set it directly to $ver_lt in a single UPDATE?

Upvotes: 1

Mathews Jose
Mathews Jose

Reputation: 409

try something like :

 done <<< "${UP_VER}"

Upvotes: 0

Related Questions