i have a list/array of per line quoted strings in a list.json file. this file is dynamically generated and fluctuates from 1 to inf in size. currently 127 elements. i need to process every line no matter if its 1 or inf.
[
"p1",
"p2",
...,
"p127"
]
these params need to be tacked onto a command flag within an array eg. command --params=["p1","p2","...","p20"]
it can take up to a max of 20 per command.
currently im just going through generating one command for every param in my list.json, using a simple for loop. eg below
lines="$(cat list.json)"
for l in ${lines} ;
do
command --params=[${l}]
done
eg. currently generates and runs 127 loops:
command --params=["p1"]
command --params=["p2"]
...
command --params=["p127"]
etc. and i save the outputs.
this is the obvs basic, and very inefficient & slow method. so ideally i want to reduce my total number of commands so its using max params eg. 20 in each loop eg.
1st loop = command --params=["p1","p2",..."p20"]
2nd loop = command --params=["p21","p22",..."p40"]
etc.
this has two problems i need to address.
i dunno how to do that in a for loop...looking at a bunch of examples of for loops for specifying some logic for sequence & increments which is obvs enough, but im really not sure what are you supposed to do where you want it to batch multiple lines per loop, eg like a range of 20 lines at a time? seems simple enough to me, but havent had to do it before.
potentially dealing with any comma separation situation from the array of params. eg. splitting the elements 20 at a time, into their own not malformed json array ie. without trailing commas etc.
CodePudding user response:
You would first join 20 elements with comma, then run your command with these as arguments.
xargs -n20 sh -c 'IFS=,; echo "$*"' - < lines.json |
xargs -I{} command --params=[{}]
I guess --params=
is expected to be a JSON array. I would suggest just using jq
to loop and split it into an arrays of 20 elements. How to split an array into chunks with jq?
jq -c '_nwise(20)' lines.json |
xargs -d '\n' -I{} command --params={}
CodePudding user response:
Here's an xargs
idea/demo:
$ seq 43 > testdata
$ n=5
$ xargs -L $n xargs bash -c '
[ $# = '$n' ] || exit
echo args = "$@"
' -- <testdata
args = 1 2 3 4 5
args = 6 7 8 9 10
args = 11 12 13 14 15
args = 16 17 18 19 20
args = 21 22 23 24 25
args = 26 27 28 29 30
args = 31 32 33 34 35
args = 36 37 38 39 40
- note that
'$n'
is actually unquoting the variable --
is a comment (see bash-c
documentation)- replace
echo
with something more interesting
CodePudding user response:
It's not clear how you want to use the lines, and xargs
is almost certainly what you want to use, but you could read several lines with something like:
#!/bin/sh
line_count=5
while for ((i=0; i < $line_count; i )); do
eval read line$i || break;
done;
test $i = $line_count
do
for ((i=0; i < $line_count; i )); do
eval "echo line $i = \$line$i"
done
done