2

This question already has an answer here:

I am working on a UPS Monitoring project using NUT Server. My objective is to make a shell script which sends one command and in response receives the status and other parameters from the UPS.

for example

#!/bin/bash
status='upsc myups' # command to get the status of UPS
sleep 1
exit 0

This is working fine for me but if I declare the 'status' as an array, the response from the ups is stored as a single element

i.e.

#!/bin/bash
declare -a status #declare status as array
# command
status=$(upsc myups)  or status=`upsc myups`
#number of array elements
echo ${status[@]}
exit 0

Number of Elements in status array:

1

Terminal Output/Array Output

echo ${#status[1]}

if I echo the array, the output looks like as follows:

Init SSL without certificate database
battery.capacity: 9.00 battery.charge: 90 battery.charge.low: 20                                                                 
battery.charge.restart: 0 battery.energysave: no battery.protection: yes  
ups.shutdown: enabled ups.start.auto: yes ups.start.battery: yes   
ups.start.reboot: yes ups.status: OL CHRG ups.test.interval: 604800 
ups.test.result: Done and passed ups.timer.shutdown: -1     
ups.timer.start: -1   
ups.type: offline / line interactive ups.vendorid: 0463

As this whole output is saved in a single element of "status" array. I am getting trouble using all the parameter separately for log purposes.

Desired Output:

battery.capacity: 9.00
battery.charge: 90 
battery.charge.low: 20                                                                 
battery.charge.restart: 0
battery.energysave: no 
battery.protection: yes

How can I separate each parameter into an individual element of an array or variable?

Please help

Thank you

marked as duplicate by PersianGulf, roaima, mdpc, user34720, garethTheRed May 25 '16 at 6:27

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

  • if you browse through the post: in the third section I have posted the output in response to the command: "Init SSL without certificate database" – Kunal Sonone May 24 '16 at 21:06
  • The output of the array and terminal output is similar. – Kunal Sonone May 24 '16 at 21:09
  • Currently, the output of the terminal/command response is saved into a single element of the array. And my goal is to separate this string into small chunks to create a saperate array or variables. Which I can use for logging – Kunal Sonone May 24 '16 at 21:13
1

The data you get back from upsc is of the form keyword: value, one per line. You can pass this through sed to get the form [keyword]="value", and then use this to initialise an associative array:

declare -A status="($(upsc myups | sed 's/\(.*\): \(.*\)/ [\1]="\2"/'))"

Now you can get the value of any keyword, eg echo "${status[device.model]}". You can loop through all the keys and values and do what you want:

for key in "${!status[@]}"
do    echo "$key: ${status[$key]}"
done

Note, if you quote your values,

status="$(upsc myups)"
echo "${status[@]}"

you would have still got a single value, but each value would be on a new line, as in your desired output.

1

You might consider:

upsc myups | grep -oP 'battery(\.\w+)+: \S+'

Your primary need is to quote your variables:

status=$(upsc myups)
echo "$status"
  • This method is working well to separate each parameter with the help of initial word. But the output is still a single string. I want to separate every element and save it in an array or a variable. Please help – Kunal Sonone May 24 '16 at 21:55
  • Then meuh's answer is what you want – glenn jackman May 24 '16 at 21:59
0

You could use readarray bash builtin:

readarray status < <(upsc myups)
0

The simplest solution is to assign an array (i.e. enclosed in parentheses) rather than a string to $status.

Also set IFS to a newline (\n) so that it puts each line (rather than each word) into a separate array element:

$ IFS=$'\n' status=( $(upsc myups 2>/dev/null | grep '^battery\.') )

$ printf "%s\n" "${status[@]}"
battery.capacity: 9.00
battery.charge: 90
battery.charge.low: 20
battery.charge.restart: 0
battery.energysave: no
battery.protection: yes

$ declare -p status   # reformatted slightly for readability.
declare -a status='([0]="battery.capacity: 9.00" [1]="battery.charge: 90"
                    [2]="battery.charge.low: 20" [3]="battery.charge.restart: 0"
                    [4]="battery.energysave: no" [5]="battery.protection: yes")'

PS: If you're going to do significantly more processing with these upsc values, I strongly recommend using perl or awk or python instead of bash - they're all far better suited to writing complex text-processing tools than bash alone.

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