来自 stdin 的 While 循环

来自 stdin 的 While 循环

我的任务是执行以下操作:

从未给出名称的标准输入(可能是一个文件,但我不确切知道它)中,对其进行处理以重现此内容:

2021-07-06 - 12:45:12 - 218.251.25.78 - "Through bag smile international talk."
2021-07-06 - 12:45:12 - 213.255.42.89 - "Lay point red away member network."
   ^^^         ^^^         ^^^                      ^^^
   date    hour(init)      ip                   description

这将是标准输入给出的信息

Init: 2021-07-06 12:45:12
End: 2021-07-06 13:38:09
Logfile:
1625561998 218.251.25.78 CRITICAL "Through bag smile international talk."
1625573490 223.203.248.97 ERROR "Evening message suffer certainly pretty nothing she."
1625560753 36.254.92.124 DEBUG "Future suddenly guy issue Congress feeling."
1625563857 213.255.42.89 CRITICAL "Lay point red away member network."
1625560959 107.150.127.36 DEBUG "Center nothing approach."
1625579950 54.56.188.207 DEBUG "Then final simple door sell."

只应获取带有 CRITICAL 标志的日志。

因此,我假设一段时间读取行会起作用,但我不确定如何 grep 信息并获取部分信息,然后将其全部连接起来。也许在其他编程语言中会更容易,但在 Bash 中我不知道该怎么做。

** 编辑是因为我设法用 Bash 来完成它。问题是我正在搜索一个单词,所以如果这个单词在其他地方,而不仅仅是在 $3 字段中,它也会匹配,但这是不合适的。

#!/bin/bash

while read -r line
do
    if echo $line | grep -q "CRITICAL"; then
        epoch=$(echo $line | gawk '{$1 = strftime("%F %T", substr($1,1,10))} 1')
        hDateIp=$(echo $epoch | sed 's/CRITICAL//g' | cut -d ' ' -f1-4 | sed 's/\ /\ \-\ /g')
        msg=$(echo $epoch | cut -d '"' -f2)
        echo $hDateIp \"$msg\"
    fi
done < file-ingest

我还尝试将这一行包含在条件中,但没有成功,因为输出很奇怪:

if echo $line | awk -F '[]' '$3 == "CRITICAL"'

答案1

假设您希望将1625561998... Unix 纪元时间转换为本地时间戳,而不是打印Init每行的时间,使用perl

perl -MPOSIX -lne '
  print strftime("%F - %T - ", localtime$1), "$2 - $3"
    if /^(\d+) (\S+) CRITICAL (.*)/' <your-file
2021-07-06 - 09:59:58 - 218.251.25.78 - "Through bag smile international talk."
2021-07-06 - 10:30:57 - 213.255.42.89 - "Lay point red away member network."

(更改localtimegmtime获取 UTC 时间而不是本地时间)。

任何状况之下你不应该使用 shell 循环来处理文本

答案2

#! /bin/bash

read -r dummy date time rest
read -r ignore
read -r ignore

while read -r timestamp ip category text; do
        if [ "$category" = 'CRITICAL' ]; then
                printf '%s - %s - %s - %s\n' "$date" "$time" "$ip" "$text"
        fi
done

答案3

使用Perl(仅内置,无需安装模块):

我转换Unix epoch time根据我们对您问题的评论,您在问题中指定的人类可读格式:

<INPUT> |
perl -MPOSIX -ane '
    CORE::say join " ", strftime("%F - %T -", localtime $F[0]), @F[1..$#F]
        if $F[0] =~ /^\d+$/ and $F[2] eq "CRITICAL"
'

2021-07-06 - 10:59:58 - 218.251.25.78 CRITICAL "Through bag smile international talk."
2021-07-06 - 11:30:57 - 213.255.42.89 CRITICAL "Lay point red away member network."

相关内容