Hey everyone,
I'm new to Linux and I'm trying to write a script that uses mkvmerge to extract information from a .mkv file. However, I'm stuck trying to convert the JSON output from mkvmerge into a bash array. I've done a bit of searching on Stack Overflow but none of the solutions have worked for me.
Here's what I've tried:
```bash
dir="/mnt/Anime/Series/KonoSuba/Season 2/[Nep_Blanc] KonoSuba II 10.mkv"
ARRAY_SIZE=$(mkvmerge -J "$dir" | jq '.tracks | length')
count=0
arr=()
while [ $count -lt $ARRAY_SIZE ];
do
arr+=($(mkvmerge -J "$dir" | jq '.tracks'[$count]))
((count++))
done
```
I also attempted using readarray:
```bash
readarray -t test_array < <(mkvmerge -J "$dir" | jq '.tracks')
for element in "${test_array[@]}";
do
echo "$element"
done
```
I even tried this:
```bash
array=($(mkvmerge -J "$dir" | jq '.tracks' | sed -e 's/^[/(/' -e 's/]$/)/'))
```
The issue is that when I echo the array, it prints each line instead of specific JSON objects. I'm really hoping to get some help to sort this out as I originally wanted to improve my bash scripting skills. Any advice would be greatly appreciated!
6 Answers
If you're having issues with the output appearing as lines, just remember to keep using `-r` with jq to get raw output. It saves a lot of formatting troubles!
It sounds like you're almost there! Instead of just echoing, you might want to refine your use of jq. Try using `jq -r '.tracks[]'` which should give you the raw JSON objects in a proper format. Here's a quick example:
```bash
readarray -t items < <(jq -r '.tracks[]' < <(mkvmerge -J "$dir"))
```
This will fill your array with each JSON object from the tracks. Give it a shot and let us know how it goes!
You can also achieve this with a combination of `jq` and `readarray`. Using this line should do the trick:
```bash
readarray -t arr < <(jq -r '.tracks[]' < "$dir")
```
This directly populates the `arr` bash array with each track from the JSON. It's cleaner and should help you avoid the line output problems you were facing. Let me know if that works!
Awesome, I appreciate the suggestion!
I had a similar situation and ended up writing a function for it! You could use something like this:
```bash
json2array() {
readarray -t arr < <(jq -r '.tracks[]' < "$1")
}
json2array your_file.json
```
This can be pretty handy if you're dealing with JSON frequently. Just pass your JSON file to the function whenever you need!
Another approach would be to convert your JSON directly into a bash associative array if you need to store key-value pairs. Here's a short function:
```bash
json2hash () {
readarray -d '' proto < <(jq -r 'to_entries|map(.key + "u0000" + .value)|.[]' "$1")
for item in "${proto[@]}"; do
IFS='u0000' read -r key value <<< "$item"
declare -gA arr
arr["$key"]="$value"
done
}
json2hash your_file.json
```
This will let you access each item by key in your bash script. Good luck with your scripting!
One last tool to consider is jq's built-in support to handle shell output cleanly. You might want to check out the `@sh` filter which formats the output in a way that's more bash-friendly. Just make sure to run it in a subshell to handle the conversion right!
Thanks, I’ll test that out and get back to you!