grep 相同匹配不同打印

grep 相同匹配不同打印

早些时候用 grep 在这里得到了一些有价值的帮助,所以希望我也能解决这个问题。

这是来自 Rclone 日志

Transferred:      577.080M / 577.080 MBytes, 100%, 12.660 MBytes/s, ETA 0s
Errors:                 0
Checks:                 2 / 2, 100%
Transferred:            2 / 2, 100%
Elapsed time:       45.5s

我想做的是创建带有自定义文本的电子邮件通知。类似“传输 577 MB,2 个文件在 45.5 秒内出现 0 个错误 @ 12,660 MBytes/s”

因此,为了使其工作,我需要打印这些值。我按照以前的方法尝试过,但没有成功。在日志中传输两次,如何拆分它们以获得 TRF= 577.080Mbytes 和 TRS= 12.660 MBytes/s

TRF=$(grep -o 'Transferred:.*' $logfile| cut -d\   -f4)
ERR=$(grep -o 'Errors:.*' $logfile | cut -d\   -f4)
TIM=$(grep -o 'Elapsed time:.*' $logfile | cut -d\   -f3-)
TRS=$(grep -o 'Transferred:.*' $logfile | cut -d\   -f4)

答案1

转移因子:

$ grep -Pom1 'Transferred:.*/ \K[^,]*' "$logfile"
577.080 MBytes
  • -P启用与 perl 兼容的正则表达式,并且在匹配的输出中\K不包含之前的内容\K
  • -o只输出该行的匹配部分
  • -m1在第一个匹配的行之后退出以排除第二Transferred:

TRS:

$ grep -Po 'Transferred:[^,]*,[^,]*, \K[^,]*' "$logfile"
12.660 MBytes/s
  • 与 TRF 类似:获取第二个逗号 + 不是逗号的空格后面的所有内容
  • 我们不需要-m1这里,因为模式包含多个逗号

:

$ grep -Po 'Errors:[[:space:]]*\K.*' "$logfile"
0
  • 只获取行尾的数字,去掉空格字符

TIM:

$ grep -Po 'Elapsed time:[[:space:]]*\K.*' "$logfile"
45.5s

传输文件数:(这是两个数字中的第一个)

$ grep -Po 'Transferred:[[:space:]]*\K[0-9]+(?= /)' "$logfile"
2
  • (?= /)是一个积极的前瞻(PCRE),我们正在寻找一个空间 和/。这部分就像\K不包含在匹配的输出中一样,并且需要不匹配第一Transferred行。

答案2

这种方法仅使用单个进程即可创建整个输出线。因此,它应该比使用一系列 grep 和 cut 快得多。此外,awk 非常强大(例如,它可以进行浮点数学运算),如果您稍后对输出进行增强,这可能会很有用。

尝试:

$ awk '/ETA/{mb=$2; speed=$7" "$8} /Errors/{err=$2} /Transferred/{n=$2} /Elapsed/{printf "Transferred %s, %s files with %s errors in %s @ %s\n",mb,n,err,$3,speed}' rclone.log 
Transferred 577.080M, 2 files with 0 errors in 45.5s @ 12.660 MBytes/s,

怎么运行的

  • /ETA/{mb=$2; speed=$7" "$8}

    如果当前行包含 ETA(意味着它是第一Transferred行),则将第二字段保存在 中mb,第七和第八字段保存在 中speed

  • /Errors/{err=$2}

    如果该行包含Errors,则将第二个字段保存在 中err

  • /Transferred/{n=$2}

    如果该行包含Transferred,则将第二个字段保存在变量中n

  • /Elapsed/{printf "Transferred %s, %s files with %s errors in %s @ %s\n",mb,n,err,$3,speed}'

    最后,当我们到达包含 的行时Elapsed,打印出我们的消息。

多行版本

对于那些喜欢将代码分散在多行中的人:

awk '
/ETA/{
    mb=$2
    speed=$7" "$8
}
/Errors/{
    err=$2
}
/Transferred/{
    n=$2
}
/Elapsed/{
    printf "Transferred %s, %s files with %s errors in %s @ %s\n",mb,n,err,$3,speed
}' rclone.log 

相关内容