Nick Andriopoulos
Nick Andriopoulos

Reputation: 10643

Parsing command output in bash to variables

I have a number of bash scripts, each doing its own thing merrily. Do note that while I program in other languages, I only use Bash to automate things, and am not very good at it.

I'm now trying to combine a number of them to create "meta" scripts, if you will, which use other scripts as steps. The problem is that I need to parse the output of each step to be able to pass a part of it as params to the next step.

An example:

stepA.sh

[...does stuff here...]
echo "Task complete successfuly"
echo "Files available at: $d1/$1"
echo "Logs available at: $d2/$1"

both the above are paths, such as /var/www/thisisatest and /var/log/thisisatest (note that files always start with /var/www and logs always start with /var/log ). I'm only interested in the files path.

steB.sh

[...does stuff here...]
echo "Creation of $d1 complete."
echo "Access with username $usr and password $pass"

all variables here are simple strings, that may contain special characters (no spaces)

What I'm trying to build is a script that runs stepA.sh, then stepB.sh and uses the output of each to do its own stuff. What I'm currently doing (both above scripts are symlinked to /usr/local/bin without the .sh part and made executable):

 #!/bin/bash

 stepA $1 | while read -r line; do
 # Create the container, and grab the file location
 # then pass it to then next pipe
   if [[ "$line" == *:* ]]
   then
     POS=`expr index "$line" "/"`
     PTH="/${line:$POS}"
     if [[ "$PTH" == *www* ]]
     then
       #OK, have what I need here, now what?
       echo $PTH;
     fi
   fi
done 

# Somehow get $PTH here

stepB $1 | while read -r line; do
 ...
done

#somehow have the required strings here

I'm stuck in passing the PTH to the next step. I understand this is because piping runs it in a subshell, however all examples I've seen refer to to files and not commands, and I could not make this to work. I tried piping the echo to a "next step" such as

stepA | while ...
    echo $PTH
done | while ...
 #Got my var here, but cannot run stuff
done

How can I run stepA and have the PTH variable available for later? Is there a "better way" to extract the path I need from the output than nested ifs ?

Thanks in advance!

Upvotes: 2

Views: 5974

Answers (1)

Gordon Davisson
Gordon Davisson

Reputation: 125708

Since you're using bash explicitly (in the shebang line), you can use its process substitution feature instead of a pipe:

while read -r line; do
    if [[ "$line" == *:* ]]
        .....
    fi
done < <(stepA $1)

Alternately, you could capture the command's output to a string variable, and then parse that:

output="$(stepA $1)"
tmp="${output#*$'\nFiles available at: '}" # output with everything before the filepath trimmed
filepath="${tmp%%$'\n'*}" # trim the first newline and everything after it from $tmp
tmp="${output#*$'\nLogs available at: '}"
logpath="${tmp%%$'\n'*}"

Upvotes: 4

Related Questions