通过外部bash函数解析JQ输出?

时间:2018-03-07 00:53:50

标签: bash parsing logging jq tail

我想从包含JSON sting的日志文件中解析数据,我想知道是否有一种方法让我使用bash函数来执行任何自定义解析而不是重载jq命令。

命令:

tail errors.log --follow | jq --raw-output '. | [.server_name, .server_port, .request_file] | @tsv' 

输出:

8.8.8.8     80     /var/www/domain.com/www/public

我想解析第3列以剪切字符串以排除/var/www/domain.com部分,其中/var/www/domain.com是文档根目录,/var/www/domain.com/subdomain/public是网站的公共html部分。因此,我希望将输出保留为/subdomain/public(或示例/www/public)。

我想知道我是否能以某种方式注入一个bash函数来解析.request_file列?或者我将如何使用jq

执行此操作

我遇到了输出此命令任何部分输出的问题,这些输出允许我进行任何类型的字符串操作。

1 个答案:

答案 0 :(得分:2)

使用BashFAQ #1 while read循环来迭代这些行,并使用BashFAQ #100 parameter expansion来执行所需的修改:

tail -f -- errors.log \
  | jq --raw-output --unbuffered \
       '[.server_name, .server_port, .request_file] | @tsv' \
  | while IFS=$'\t' read -r server_name server_port request_file; do
      printf '%s\t%s\t%s\n' "$server_name" "$server_port" "/${request_file#/var/www/*/}"
    done

注意使用--unbuffered来强制jq立即刷新其输出行而不是缓冲它们。这会带来性能损失(因此它不是默认值),但它确保您在从可能较慢的输入源读取时立即获得输出。

也就是说,在jq中删除前缀也很容易,因此上面没有特别的理由:

tail -f -- errors.log | jq -r '
  def withoutPrefix: sub("^([/][^/]+){3}"; "");
  [.server_name, .server_port, (.request_file | withoutPrefix)] | @tsv'