Luo*_*Son 3 grep awk quoting jq
基本上我有一个 file.log 如下
blah blah
blah blah
Hello world | {"foo": "bar"}
blah blah
Hello earth | {"foo1": "bar1"}
Run Code Online (Sandbox Code Playgroud)
现在我的目标是编写一些 shell 命令来获得如下输出:
Hello earth | "bar"
Hello earth | "bar1"
Run Code Online (Sandbox Code Playgroud)
目前这是我所拥有的:
grep Hello file.log | awk -F "|" '{print $1, system("jq " $2)}'
Run Code Online (Sandbox Code Playgroud)
但是调用 jq 给了我这个错误:
jq: error: syntax error, unexpected ':', expecting $end (Unix shell quoting issues?) at <top-level>, line 1:
bin:application
jq: 1 compile error
Run Code Online (Sandbox Code Playgroud)
我想是因为在 system() 里面,我的 $12 被去掉了所有的引号字符 (") 因此 JQ 无法识别它的 json。有什么建议吗?
system不返回要打印的内容,它返回您执行的命令的退出值(如果一切正常,则为 0)。您将看到您的 JSON 解码数据,然后是一行Hello earth 0jq {foo: bar}(两个参数,不再引用 JSON)$2包含特殊字符,如$,您的外壳将解释它们jq也不会这样调用,它需要一个过滤器作为第一个参数(比如“ .”),并且它需要从文件或标准输入中读取 JSON 输入$2是; rm -rf ~?)。如果可以,最好避免它。撇开安全问题不谈,这里是一个awk大部分时间都可以工作的代码:
awk -F "|" '{ printf "%s", $1; system("echo \x27" $2 "\x27 | jq .")}'
Run Code Online (Sandbox Code Playgroud)
它的作用是将$2括在单引号 ( \x27) 中的内容发送jq到标准输入。
$2包含单引号,它将破坏整个命令$2以破折号开头(不太可能),它将被解释为一个选项echo(我们可以使用printf命令而不是echo)$2包含...'; rm -r ~; : ' ...字符串中的任何位置)awk代码awk -F "|" '{ printf "%s", $1; print $2 | "jq ."; close("jq ."); }'
Run Code Online (Sandbox Code Playgroud)
由于通过 stdin$2发送到jq进程,但现在使用awk管道,它不再被 shell 解释,解决了上述所有问题。该jq命令必须在每一行关闭(终止),因此调用close().