Home > Back-end >  Bash, pattern substitution for json-like multiline string
Bash, pattern substitution for json-like multiline string

Time:08-31

I wrote a bash script that essentially turns df -a command into multiple, new-line separated, Json formatted objects.

PATTERN='!/loop/ && /^\// {printf \
"\"disk.device\":\"%s\","\
"\"disk.mount\":\"%s\","\
"\"disk.total\":%d,"\
"\"disk.used\":%d,"\
"\"disk.free\":%d,"\
"\"disk.percentage\":%.2f\n", $1, $6, $2, $2-$4, $4, ($2-$4)/($2 1)*100}'

MODE=""
NAME="disk.device"
PAYLOAD="$(df -a | awk "$PATTERN")"

jsonify.sh $MODE "$PAYLOAD"

The script works in two steps:

  • creating a "proto-json" payload
  • converting it into actual json

The $PAYLOAD variable is constructed via awk and then passed to the jsonify function.

Here is an example output:

"disk.device":"/dev/nvme0n1p2","disk.mount":"/","disk.total":47745772,"disk.used":29455764,"disk.free":18290008,"disk.percentage":61,69
"disk.device":"/dev/nvme0n1p1","disk.mount":"/boot/efi","disk.total":583544,"disk.used":5356,"disk.free":578188,"disk.percentage":0,92
"disk.device":"/dev/nvme0n1p4","disk.mount":"/home","disk.total":427115864,"disk.used":46328340,"disk.free":380787524,"disk.percentage":10,85
"disk.device":"/dev/fuse","disk.mount":"/run/user/1000/doc","disk.total":0,"disk.used":0,"disk.free":0,"disk.percentage":0,00

Unfortunately a new requirement emerged, and now the value of the "disk.device" needs to be substituted from the actual name of the disk to disk_n, where n is an integer.

In the above example the result would look like:

"disk.device":"disk_0","disk.mount":"/","disk.total":47745772,"disk.used":29455764,"disk.free":18290008,"disk.percentage":61,69
"disk.device":"disk_1","disk.mount":"/boot/efi","disk.total":583544,"disk.used":5356,"disk.free":578188,"disk.percentage":0,92
"disk.device":"disk_2","disk.mount":"/home","disk.total":427115864,"disk.used":46328340,"disk.free":380787524,"disk.percentage":10,85
"disk.device":"disk_3","disk.mount":"/run/user/1000/doc","disk.total":0,"disk.used":0,"disk.free":0,"disk.percentage":0,00

Is it possible to work out a solution using a single command (maybe awk?) or do i need an explicit loop that goes trough all the lines of the payload? In case of the latter how would you proceed ?

CodePudding user response:

echo "$output" | awk -F, -v OFS=, '{
    disk_n = "disk_" (NR - 1)
    sub(/"[^"] "$/, "\"" disk_n "\"", $1)
    print
}'

CodePudding user response:

In GNU AWK one might use postincrease to get running number starting at zero, consider following example, let file.txt content be

100
1000
10
10000
1
100000

and you want to output ordinal followed by numer for values >= 500, then you might do

awk '$1>=500{printf "%d %s\n", i  , $1}' file.txt

which gives output

0 1000
1 10000
2 100000

(tested in gawk 4.2.1)

  • Related