I have to create a simple bash script that converts .txt outputs to JSON code. The pattern is as follows:
[ Example ], 1..3 tests
-----------------------------------------------------------------------------------
not ok 1 text1 (text1), 5ms
ok 2 text2 (text2, issues), 2ms
ok 3 text3 (text3, issues), 15ms
-----------------------------------------------------------------------------------
2 (of 3) tests passed, 1 tests failed, rated as 66.66%, spent 22ms
This will have to be converted to the following JSON (as an example):
{
"testName": " Example ",
"tests": [
{
"name": "",
"status": false,
"duration": ""
},
{
"name": "",
"status": true,
"duration": ""
}
],
"summary": {
"success": ,
"failed": ,
"rating": ,
"duration": ""
}
}
I managed to almost complete the requirements, the test name is taken out correctly from the txt and also the summary results are taken correctly, but the only problem is with the tests part which does not work at all, not even the variables set upfor that are recognosed.
My code is:
#!/bin/bash
###################PREREQUISITES#####################
# Check if the output file is provided as an argument (I chose to do so to be able tospecify location)
if [ $# -eq 0 ]; then
echo "Usage: $0 <output_json_file>"
exit 1
fi
input_file="example_file.txt" #File that is being used as source to convert FROM
output_file=$1 #Output file location as an argument to convert TO
# Check if the input file exists
if [ ! -f "$input_file" ]; then
echo "Input file '$input_file' not found."
exit 1
fi
###################CODE#####################
#Setting up a pattern variable for the lines with the values that we need as JSON variables:
pattern='"^(ok|not ok)[[:space:]]{2,}([0-9])[[:space:]]{2,}(.+),[[:space:]]+([0-9]{1,3}ms)$"'
# Read the input_file line by line:
while IFS= read -r line; do
# Extract the test_Name from the first line -> IT WORKS
if [[ "$line" =~ [([^]]+)] ]]; then
testName="${BASH_REMATCH[1]}"
# Extract values using BASH_REMATCH on the pattern variable -> IT DOES NOT WORK
elif [[ "$line" =~ $pattern ]]; then
status="${BASH_REMATCH[1]}"
status_code="${BASH_REMATCH[2]}"
name="${BASH_REMATCH[3]}"
duration="${BASH_REMATCH[4]}"
break
elif [[ "$line" =~ ^([0-9]+) (of [0-9]+) tests passed, ([0-9]+) tests failed, rated as ([0-9.]+)%, spent ([0-9]+)ms$ ]]; then
success="${BASH_REMATCH[1]}"
failed="${BASH_REMATCH[2]}"
rating="${BASH_REMATCH[3]}"
duration="${BASH_REMATCH[4]}ms"
break
fi
done < $input_file
# Construct the JSON output
output_json="{
"testName": "$testName",
"tests": [
${tests[@]}
],
"summary": {
"success": $success,
"failed": $failed,
"rating": $rating,
"duration": "$duration"
}
}"
# Write the JSON output to the output file
echo "$output_json" > "$output_file"
echo "Conversion completed. JSON output written to $output_file"
As for now the status is that either only the Name works, so the TESTS and SUMMARY section is not filled in to the JSON file, or (if modified with removing tests) the NAME and SUMMARY works but TESTS dont.
What am I doing wrong? Is there something I am doing fundamentally wrong with this?
Thanks for the advice in advance!
2
Answers
2 observations:
tests
array that you use to construct the JSON outputjq
to build JSONjq
as mentioned is the "go-to" tool for dealing with JSON.One useful feature is the
capture()
function which will build an object from named capture groups.