0

I am trying to write a bash script that generates uuids and writes that to a file, in a json array format. I have written a simple code that generates the id and writes to a file but the issues i am running into are;

here is my own implementation

function uud {
     for ((i=1;i<=$1;i++));
     do 
         echo "\`uuidgen\`", >> $file
     done 
 }

 for file in file1.json file2.json;
 do 
     $( uud $1)
done
  1. I am having issues with converting the ids into strings.
  2. Converting the results to arrays.

Currently my solution prints the ids into the file in this format

caca8fef-42d6-4b21-9d6b-0e40d348bd53,
e6e12fb5-4304-4ba9-b895-931bb4b58fbf,
df699ecd-d887-413e-8383-2a98ac2fa22f,

and this is what i want to acheive, How can I go about getting this result?

[
"caca8fef-42d6-4b21-9d6b-0e40d348bd53",
"e6e12fb5-4304-4ba9-b895-931bb4b58fbf",
"df699ecd-d887-413e-8383-2a98ac2fa22f"
]
wyn
  • 141
  • 1
  • 13

3 Answers3

3

Use jq to generate the JSON.

uud () {
    for ((i=0; i< $1; i++)); do
        uuidgen
    done
}

for file in file1.json file2.json; do
    uud 5 | jq -Rs 'rtrimstr("\n") | split("\n")' > "$file"
done

-Rs reads the entire input into a single JSON string, which you then split (after removing the trailing newline) on newlines to produce the desired array.


One blogger suggests using two jq processes, which is more expensive but arguably simpler:

for file in file1.json file2.json; do
   uud | jq -R . | jq -s . > "$file"
done
chepner
  • 497,756
  • 71
  • 530
  • 681
  • End up with a trailing empty string in your list from the `split()` treating the terminating newline from the last entry as a split point. Maybe add a `[:-1]`? – Charles Duffy Sep 15 '22 at 13:37
  • Thanks; I've opted to strip the trailing newline before splitting. – chepner Sep 15 '22 at 13:39
  • (An alternative that I found while researching would be to use `jq` twice: `jq -R . | jq -s .`. I think a single process is still preferable, but the simplicity of the two separate commands is compelling.) – chepner Sep 15 '22 at 13:41
  • Single `jq` process, but not sure it is much easier to read: `jq --null-input '$ARGS.positional' --args $(uud 5) > "$file"` – j_b Sep 15 '22 at 16:40
  • Hm, `ARGS.positional` is newer, so I didn't think of that. I'm not crazy about the unquoted command substitution, but it *should* be safe assuming a standard value for `IFS`. – chepner Sep 15 '22 at 16:49
1

I have adjusted slightly your script, try it:

function uud {
    echo "[" > $file
    for ((i=1;i<$1;i++));
    do 
        echo \"$(uuidgen)\", >> $file
    done 
    echo \"$(uuidgen)\" >> $file           # last item in array without comma 
    echo "]" >> $file
 }

for file in file1.json file2.json;
do 
    $( uud $1)
done

Or execute it here and check the result.

m19v
  • 1,800
  • 4
  • 11
  • 26
  • `$(uud $1)`, not `uud "$1"` on its own? Why would you want to tell the shell to read the uud function's stdout and run that stdout as a separate command? – Charles Duffy Sep 15 '22 at 13:43
  • For that matter, is there a good reason for making uud depend on a global `file` variable instead of having it write to stdout? Taking all the `>$file` and `>>$file` out of the function and just invoking it with `uud >"$file"` would be a lot more clear. – Charles Duffy Sep 15 '22 at 13:44
  • ...the other thing is that the unquoted expansions you're doing are arguably safe with `uuidgen` but would be unsafe with other programs (things able to contain whitespace-surrounded wildcards in their output, f/e). Consider trying to make your code run [shellcheck](http://shellcheck.net/)-clean to reduce the likelihood of folks adapting it to different use cases tripping over bugs. – Charles Duffy Sep 15 '22 at 13:45
  • My intention here was adjust his own solution as minimal as possible. – m19v Sep 15 '22 at 13:51
0

After you've run your existing loop...

#!/bin/sh
cat > ed1 <<EOF
%s/^/"/g
%s/$/"/g
$s/,//
1i
[
.
$a
]
.
wq
EOF

ed -s file < ed1
petrus4
  • 616
  • 4
  • 7