我有一堆由标签分隔的两列日志。第二列是有效的JSON:
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"}
我的目标是保留timestamp列,并打印catId
属性:
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
到目前为止,我一直试图用jq
插入awk
,但是我在system
命令中苦苦挣扎。
awk -F '\t' '{printf "\n %s \t %s \n", $1, system("jq .catId <<< " $2)}' file
在正确方向上的任何帮助将不胜感激。
答案 0 :(得分:5)
如果文件用制表符分隔,则可以原始读取文件,在制表符上拆分,解析并提取json,然后在制表符上重新加入。
$ jq -Rr 'split("\t") | .[1] |= fromjson.catId | join("\t")' input.log
答案 1 :(得分:1)
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 :(得分:0)
只需添加为什么您的代码无法工作的原因,因为前面的答案更好。在您的情况下,$2
将jq
解释为多个参数,因为$2
包含空格。
因此,在下面的代码中,$2
放在十六进制值中,单引号\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
答案 3 :(得分:0)
以bash播放:
while IFS=$'\t' read -r timestamp json; do
printf '%s\t%s\n' "$timestamp" "$(jq -r .catId <<<"$json")"
done < file
这将比jq oneliner慢得多。
答案 4 :(得分:0)
使用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
$