我有一堆两列日志,由制表符分隔。第二列是有效的JSON:
2019-02-28T19:43:48.585Z {“id”:1234,“catId”:42,“img”:“other.jpg”}2019-02-28T19:44:48.585Z ……
在bash中:
while IFS=$'\t' read -r timestamp json; do printf '%s\t%s\n' "$timestamp" "$(jq -r .catId <<<"$json")" done < file
这将比jq oneliner慢得多。
如果文件是制表符分隔的,则可以在原始文件中读取文件,在选项卡上拆分,解析并解压缩json,然后重新加入选项卡。
$ jq -Rr 'split("\t") | .[1] |= fromjson.catId | join("\t")' input.log
awk '{sub(/,/,"",$5);print $1"\t"$5}' file 2019-02-28T19:43:48.585Z 42 2019-02-28T19:44:48.585Z 999 2019-02-28T19:44:48.585Z 42 2019-02-28T19:46:48.585Z 765
只是添加为什么你的代码不能像以前的答案那样工作更好。在你的情况下 $2 被解释为多个参数 jq 如 $2 包含空格。
$2
jq
所以,在下面的代码中 $2 被置于十六进制值内的单引号 \x27 然后加双引号。 还有一点格式化,以保持输出在同一行。
\x27
awk -F '\t' '{printf "%s\t", $1;system("jq .catId <<< \x27"$2"\x27")}' file
输出:
2019-02-28T19:43:48.585Z 42 2019-02-28T19:44:48.585Z 999 2019-02-28T19:44:48.585Z 42 2019-02-28T19:46:48.585Z 765
使用Perl
perl -lanE ' $x=$_=~s/(^.*catId":\s*)(\d+).*$/$2/gr; print "$F[0]\t$x" '
给定的输入
$ cat test.log 2019-02-28T19:43:48.585Z {"id": 1234, "catId": 42, "img": "other.jpg"} 2019-02-28T19:44:48.585Z {"id": 4321, "catId": 999, "img": "my.jpg"} 2019-02-28T19:44:48.585Z {"id": 1234, "catId": 42, "img": "new.jpg"} 2019-02-28T19:46:48.585Z {"id": 1234, "catId": 765, "img": "cat.jpg"} $ perl -lanE ' $x=$_=~s/(^.*catId":\s*)(\d+).*$/$2/gr; print "$F[0]\t$x" ' test.log 2019-02-28T19:43:48.585Z 42 2019-02-28T19:44:48.585Z 999 2019-02-28T19:44:48.585Z 42 2019-02-28T19:46:48.585Z 765 $