如何将文件从 bash 转换为 json
How convert file to json from bash
我有一个像这样的 .file,想把它转换成 JSON 格式。
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)
代码
#!/bin/bash
json=''
while read -r line; do
dt=$(echo ${line} | awk '{print (" ")}')
info=$(echo ${line} | awk '{print ()}')
error=$(echo ${line} | awk '{print ()}')
json+="{\"date\":\"$dt\","\"info\":\"$info\",\"error\":\"$error\""}"
done < "$file"
res="$json"
如何使 var res 像 JSON 格式一样用逗号分隔符 "," 每个对象 {}
我想这样输出
[{"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"}]
但现在我的输出看起来像这样
{"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"}
对象之间没有任何分隔符
以及如何在 JSON
中处理 "/run/nginx.pid" 这样的字符串
请您尝试以下操作:
#!/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 "]"
输出:
[{"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)"}]
[编辑]
如果要将变量(例如 var
)分配给生成的 json 格式的字符串,请将整个代码用 $(
和 )
括起来,作为 command substitution
然后将变量赋值给它如:
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
printf '{"date":"%s %s","info":"%s","error":"%s"}' "$day" "$hms" "$info" "${err//\"/\\"}"
# escape double quotes in $err according to Ed Morton's suggestion
done < file
echo "]"
)
echo "$var" # just to see the result
如果有jq
也可以说:
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 "]"
正如戈登戴维森所建议的那样。
请阅读why-is-using-a-shell-loop-to-process-text-considered-bad-practice。发明shell的人也发明了awk供shell调用处理文本
假设您真的不想从每个输入行末尾的消息中截断和删除所有白色 space,并且您希望输入中的所有双引号在输出中转义,您可以这样做这在每个 Unix 机器上的任何 shell 中有效且可移植地使用任何 awk:
$ cat tst.awk
BEGIN {
printf "["
ofmt = "%s{\"date\":\"%s %s\",\"info\":\"%s\",\"error\":\"%s\"}"
}
{
error = [=10=]
sub(/([^ ]+ ){3}/,"",error)
gsub(/"/,"\\"",error)
printf ofmt, sep, , , , error
}
END { print "]" }
$ awk -f tst.awk file
[{"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)"}]
我有一个像这样的 .file,想把它转换成 JSON 格式。
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)
代码
#!/bin/bash
json=''
while read -r line; do
dt=$(echo ${line} | awk '{print (" ")}')
info=$(echo ${line} | awk '{print ()}')
error=$(echo ${line} | awk '{print ()}')
json+="{\"date\":\"$dt\","\"info\":\"$info\",\"error\":\"$error\""}"
done < "$file"
res="$json"
如何使 var res 像 JSON 格式一样用逗号分隔符 "," 每个对象 {}
我想这样输出
[{"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"}]
但现在我的输出看起来像这样
{"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"}
对象之间没有任何分隔符
以及如何在 JSON
中处理 "/run/nginx.pid" 这样的字符串请您尝试以下操作:
#!/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 "]"
输出:
[{"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)"}]
[编辑]
如果要将变量(例如 var
)分配给生成的 json 格式的字符串,请将整个代码用 $(
和 )
括起来,作为 command substitution
然后将变量赋值给它如:
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
printf '{"date":"%s %s","info":"%s","error":"%s"}' "$day" "$hms" "$info" "${err//\"/\\"}"
# escape double quotes in $err according to Ed Morton's suggestion
done < file
echo "]"
)
echo "$var" # just to see the result
如果有jq
也可以说:
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 "]"
正如戈登戴维森所建议的那样。
请阅读why-is-using-a-shell-loop-to-process-text-considered-bad-practice。发明shell的人也发明了awk供shell调用处理文本
假设您真的不想从每个输入行末尾的消息中截断和删除所有白色 space,并且您希望输入中的所有双引号在输出中转义,您可以这样做这在每个 Unix 机器上的任何 shell 中有效且可移植地使用任何 awk:
$ cat tst.awk
BEGIN {
printf "["
ofmt = "%s{\"date\":\"%s %s\",\"info\":\"%s\",\"error\":\"%s\"}"
}
{
error = [=10=]
sub(/([^ ]+ ){3}/,"",error)
gsub(/"/,"\\"",error)
printf ofmt, sep, , , , error
}
END { print "]" }
$ awk -f tst.awk file
[{"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)"}]