Home > database >  How convert file to json from bash
How convert file to json from bash

Time:01-23

I have a .file like this and want to convert it to JSON Format.

2022/01/22 21:27:56 [notice] 40#40: signal process started
2022/01/22 21:27:56 [error] 40#40: open() "/run/nginx.pid" failed (2: No such file or directory)
2022/01/22 21:28:04 [notice] 42#42: signal process started
2022/01/22 21:28:04 [error] 42#42: open() "/run/nginx.pid" failed (2: No such file or directory)

Code

#!/bin/bash
json=''
while read -r line; do
    dt=$(echo ${line} | awk '{print ($1" "$2)}')
    info=$(echo ${line} | awk '{print ($3)}')
    error=$(echo ${line} | awk '{print ($4$5$6$7$8$9$10)}')
    json ="{\"date\":\"$dt\","\"info\":\"$info\",\"error\":\"$error\""}"
done < "$file"
    
res="$json"

How to make var res be like JSON format with separator comma "," every object {}


I want to make output like this

[{"date":"2022/01/22 21:27:56","info":"[notice]","error":"40#40:signalprocessstarted"},
{"date":"2022/01/22 21:27:56","info":"[error]","error":"40#40:open()"/run/nginx.pid"failed(2:Nosuch"},
{"date":"2022/01/22 21:28:04","info":"[notice]","error":"42#42:signalprocessstarted"},
{"date":"2022/01/22 21:28:04","info":"[error]","error":"42#42:open()"/run/nginx.pid"failed(2:Nosuch"}]

but right now my output look like this

{"date":"2022/01/22 21:27:56","info":"[notice]","error":"40#40:signalprocessstarted"}{"date":"2022/01/22 21:27:56","info":"[error]","error":"40#40:open()"/run/nginx.pid"failed(2:Nosuch"}{"date":"2022/01/22 21:28:04","info":"[notice]","error":"42#42:signalprocessstarted"}{"date":"2022/01/22 21:28:04","info":"[error]","error":"42#42:open()"/run/nginx.pid"failed(2:Nosuch"}

without any separator between object

and also how to handle string like "/run/nginx.pid" this in JSON

CodePudding user response:

Would you please try the following:

#!/bin/bash

echo -n "["
while read -r day hms info err; do              # split on blank characters up to 4 words
    if (( nr   )); then                         # count the line number
        echo ","                                # append a comma after the previous line
    fi
    err="$(sed -E 's/"/\\&/g' <<< "$err")"      # escape double quotes in the message
    printf '{"date":"%s %s","info":"%s","error":"%s"}' "$day" "$hms" "$info" "$err"
done < file
echo "]"

Output:

[{"date":"2022/01/22 21:27:56","info":"[notice]","error":"40#40: signal process started"},
{"date":"2022/01/22 21:27:56","info":"[error]","error":"40#40: open() \"/run/nginx.pid\" failed (2: No such file or directory)"},
{"date":"2022/01/22 21:28:04","info":"[notice]","error":"42#42: signal process started"},
{"date":"2022/01/22 21:28:04","info":"[error]","error":"42#42: open() \"/run/nginx.pid\" failed (2: No such file or directory)"}]

[Edit]
If you want to assign a variable (e.g, var) to the generated json formatted string, enclose the entire code with $( and ), as a command substitution then assign the variable to it such as:

var=$(
echo -n "["
while read -r day hms info err; do              # split on blank characters up to 4 words
    if (( nr   )); then                         # count the line number
        echo ","                                # append a comma after the previous line
    fi
    err="$(sed -E 's/"/\\&/g' <<< "$err")"      # escape double quotes in the message
    printf '{"date":"%s %s","info":"%s","error":"%s"}' "$day" "$hms" "$info" "$err"
done < file
echo "]"
)
echo "$var"                                     # just to see the result

If jq is available, you can also say:

echo -n "["
while read -r day hms info err; do              # split on blank characters up to 4 words
    if (( nr   )); then                         # count the line number
        echo ","                                # append a comma after the previous line
    fi
    jq -cn --arg date "$day $hms" --arg info "$info" --arg error "$err" '{date:$date, info:$info, error:$error}'
done < file
echo "]"

as Gordon Davisson suggests.

  •  Tags:  
  • Related