根据特定字符串过滤行,然后只打印一些更大的属性

Filter lines based on certain string and then print only some attributes greater

我有一个包含数百万行日志的大文本文件。

我想过滤所有满足以下条件的行

  1. url 应该是 url=/v2/testB
  2. totalTime 值应大于 500
INFO|id=1|totaltime=5000|httpmethod=POST|url=/v1/testA
INFO|id=2|totaltime=200|httpmethod=POST|url=/v2/testB
INFO|id=3|totaltime=1000|httpmethod=POST|url=/v2/testB
INFO|id=4|totaltime=501|httpmethod=POST|url=/v2/testB

结果:-

id=3,totaltime=1000
id=4,totaltime=501

我试过用多个awk然后放if block,不知道能不能很快搞定?谢谢!

while IFS= read -r line; do
value=`echo $line|grep "url=/v2/testB" | awk -F"totaltime=" '{ print }'| awk -F"|" '{ print }'`
if (( $value > 500 )); then
    echo $line
fi
done < file.log

你可以使用这个 awk:

awk -F '|' -v OFS=, '$NF == "url=/v2/testB" {v=; sub(/^totaltime=/, "", v); if (v+0 > 500) print , }' file

id=3,totaltime=1000
id=4,totaltime=501

为了使其更具可读性:

awk -F '|' -v OFS=, '
$NF == "url=/v2/testB" {
   v = 
   sub(/^totaltime=/, "", v)
   if (v+0 > 500)
      print , 
}' file

如果你有 gnu-awk 那么它可以减少到:

awk -F '|' -v OFS=, '$NF == "url=/v2/testB" &&
gensub(/^totaltime=/, "", "1", )+0 > 500 {print , }' file

v+0 在 awk 中是 shorthand,用于将字符串值转换为数字。

看来你运气不错:

awk -F'|' 'BEGIN{FS="|"; OFS=","}
           { url = substr($NF,index($NF,"=")+1)
             totaltime = substr(,index(,"=")+1)
           }
           (url == "/v1/testB") && (totaltime+0 > 500) { print , }
          ' file
$ awk -F'|' -v OFS=',' '{split(,t,/=/)} =="url=/v2/testB" && t[2]>500{print , }' file
id=3,totaltime=1000
id=4,totaltime=501

使用您展示的示例,请尝试执行以下 awk 程序。

awk -F'\||totaltime=' '$NF=="url=/v2/testB" && >500{print ",totaltime="}' Input_file

解释:下面是对上述代码的详细解释。

  • 使用 awk 程序中的 -F 选项设置字段分隔符。
  • 为 Input_file.
  • 的所有行将字段分隔符设置为 |totaltime=
  • 在主程序中,检查条件: a- 如果 $NF(最后一个字段)等于 url=/v2/testB 并且 b- 第 4 个字段大于 500 然后做:
  • 打印当前行的第二个字段,后跟字符串 ,totaltime=,然后是 OP 要求输出的第 4 个字段。

所有 awk 解决方案都很棒,如果这是一个解决方案,请使用它们。

如果您想解决 Bash 的问题,您可以这样做:

while IFS='|' read -r id ti; do
    [[ "${ti#*=}" -gt 500 ]] && printf "%s,%s\n" "$id" "$ti"
done < <(grep 'url=/v2/testB$' file | cut -d '|' -f 2,3)

或者,您可以删除 cut 并保留所有五个字段:

while IFS='|' read -r c1 c2 c3 c4 c5; do
    [[ "${c3#*=}" -gt 500 ]] && printf "%s,%s\n" "$c2" "$c5"
done < <(grep 'url=/v2/testB$' file)

要么打印:

id=3,totaltime=1000
id=4,totaltime=501