As others have noted, grep
's line-buffering is the obvious cause of your problem.
However, there are other problems with what you're doing that are not so obvious.
To start with, it looks like you're using sed
to add apostrophes to the start and end of each output line so you can feed it into xargs
. This isn't even remotely necessary - xargs
has -d
option you can use to tell it to use newlines as delimiter: e.g. xargs -d'\n' -r
(the -r
option is to make sure xargs
does nothing if there are no input lines)
Secondly, you're using regular expressions to parse json data. This is unreliable, extremely difficult or even impossible to get right with complex/nested structures, fragile, and prone to break at the drop of a hat for exactly the same reasons that using regexps to parse XML or HTML is unreliable, extremely difficult, and fragile. Don't parse XML or HTML with regular expressions. It doesn't work. The same applies to json.
Instead, you should use something like jq
or jsonpipe
to extract fields from json data. For example:
jq -c 'select(.twNotif.action == "add")' file.txt |
xargs -d'\n' -r -L 1 -P 5 ./testscript.sh
If you only wanted to pipe the value of the action field to xargs
(without the double-quotes), you could do it like this:
jq 'select(.twNotif.action == "add") | .twNotif.action' file.txt |
sed -e 's/"//g' |
xargs -d'\n' -r -L 1 -P 5 ./testscript.sh
Using jsonpipe
and awk
would probably be easier for a job like that:
jsonpipe < file.txt |
awk '$1 == "/twNotif/action" {gsub(/"/,""); print $2}' |
xargs -d'\n' -r -L 1 -P 5 ./testscript.sh
(note the redirection there, unlike jq
, jsonpipe
works only with stdin).
BTW, jsonpipe
transforms json data into a line-oriented format suitable for using with line-oriented tools like sed
, grep
, awk
, etc. For example:
$ jsonpipe < file.txt
/ {}
/twNotif {}
/twNotif/originator "api"
/twNotif/chain "test"
/twNotif/txId "08640-0050568a5514"
/twNotif/version "1.0"
/twNotif/msgType "api"
/twNotif/twData {}
/twNotif/twData/api {}
/twNotif/twData/api/hostId "007bdcc5"
/twNotif/twData/api/user "test"
/twNotif/twData/api/cmdTxt "100599"
/twNotif/action "add"
/twNotif/store "test"
/twNotif/msgTime 1467280648.971042
It's easier to work with than jq
, especially if you don't need json-formatted output.
It's also useful for listing the structure of and fields/elements in a json file in form that can easily be used with jq
. e.g.:
$ jsonpipe <file.txt | awk '{gsub(/\//,"."); print $1}'
.
.twNotif
.twNotif.originator
.twNotif.chain
.twNotif.txId
.twNotif.version
.twNotif.msgType
.twNotif.twData
.twNotif.twData.api
.twNotif.twData.api.hostId
.twNotif.twData.api.user
.twNotif.twData.api.cmdTxt
.twNotif.action
.twNotif.store
.twNotif.msgTime