Jiggly
Jiggly

Reputation: 23

How to storing values from a CLI tool to use in later in the same bash script?

Hello Amazing Stack Overflow People,

I'm stuck on storing values that are returned when using a CLI tool in my bash script, my goal to automate a number of commands I have to run each time I set up new devices for a customer. I'm pretty much having to do this on every product, and want to create a script to automate the routine.

#!/bin/bash
particle usb start-listening

RESULT=$(particle serial identify $OUTPUT) 
if [ $? -eq 0 ]; then
    printf '%s\n' "$RESULT"
else
    printf '%s\n' "No Match"
fi

This returns this text to the terminal

Your device id is e00fce681fffffffffc08949b
Your IMEI is 352999999084606
Your ICCID is 8901413111111117667
Your system firmware version is 1.5.0

My goal is to store the device id and the ICCID to then use in the next few particle-CLI commands.

Like this curl request that activates the sim card,

curl -X PUT https://api.particle.io/v1/sims/<$ICCID> \
       -d action=activate \
       -d access_token=<$ACCESS_TOKEN>

and adding the device to our account for testing

particle device add <device_id> 

I've spent the morning trying different tutorials and commands to parse the return data from the first command and store the devcie_ID and the ICCID to no avail.

I've tried awk:

read deviceId IMEI ICCID <<< $("particle serial identify" | awk '/is[[:space:]]/ { print $2 }')

I've tried IFS=' ':

IFS=' ' 
read -r first second third fourth fifth sixth seven eight night ten eleven twelve thirten fourten fiften sizten seventen <<< "$RESULT"
read -a strarr <<< "$RESULT"
for val in "${strarr[@]}";
do
  echo "$strarr\n"
done

I've never written a bash script before so any help pointing to better documentation on how to do this, I'm happy to read and learn. I just don't think I completely understand how bash handles Strings yet and have not found any documentation that explains what going on.

I'm hoping someone with more experience in bash scripting can point me in the right direction.

At some point, when I have more want to write a Node program to handle the setting up and testing each device during manufacturing, I'm also interested in learning how to create a Go CLI tool to manage our devices in the future.

I'm not even sure if what I'm trying to accomplish can be done with just a bash script.

Cheers, N

Upvotes: 0

Views: 185

Answers (2)

Gordon Davisson
Gordon Davisson

Reputation: 125998

First, some general scripting recommendations: It's safest to use lower- or mixed-case variable names (e.g. result or Result instead of RESULT), to avoid conflicts with the various all-caps names that have special meanings or functions. Run your scripts through shellcheck.net, as it's good at spotting common scripting mistakes. And if you're trying to debug a script, add the command set -x before the trouble section to get an execution trace of what's happening (and set +x after it, to turn off tracing).

As for extracting relevant info from a string like this: there are a number of ways to do it, all a bit clunky, and which one to use is mostly a matter of personal preference. In this situation, I'd tend to use sed to extract the relevant bits:

deviceID=$(sed -n 's/^[[:space:]]*Your device id is //p' <<<"$result")
iccid=$(sed -n 's/^[[:space:]]*Your ICCID is //p' <<<"$result")

Explanation: sed normally passes through all input (after it's modified), but -n tells it not to pass anything through (i.e. "print" it) unless explicitly told to. s/^[[:space:]]*Your device id is //p tells it to replace some spaces followed by "Your device id is " with the empty string, and then print the result; since that leaves just the device id (and the "print the result" only happens on the line where the substitution happened), it prints just the device id.

You could do it just as well with awk:

deviceID=$(awk '/Your device id is / {print $NF}' <<<"$result")
iccid=$(awk '/Your ICCID is / {print $NF}' <<<"$result")

Here the /Your device id is / means "on lines matching this string" and {print $NF} prints the last (space-delimited) field on the line.

Yet another method is to use bash's built-in variable trimming modifiers:

tempString=${result#*Your device id is }
deviceID=${tempString%%$'\n'*}
tempString=${result#*Your ICCID is }
iccid=${tempString%%$'\n'*}

Here, the #*Your ICCID is modifier to the variable expansion removes from the beginning of the string (#) through (*) the string "Your ICCID is ", and then %%$'\n'* removes from the end (%%) to a newline (the double-%% makes it remove as much as possible, i.e. starting at the first, rather than last, newline character). See here for more info about these (and other) modifiers.

BTW, when you get the RESULT string, you use the command particle serial identify $OUTPUT. What is $OUTPUT? the variable doesn't appear to be set to anything, so (since it's not double-quoted) it'll just vanish from the command. Is that intentional?

Upvotes: 1

lain0
lain0

Reputation: 109

You can save output of command to variable file and parse necessery variables

file=$(particle serial identify $OUTPUT) 
device_id=$(echo $file| grep -Eo 'device id is .+?$' |sed 's/device id is //g')
ICCID=$(echo $file| grep -Eo 'ICCID is .+?$' |sed 's/ICCID is //g')
echo $device_id
echo $ICCID

Upvotes: 0

Related Questions