awk 匹配第三个和第四个模式并将其打印在一行中

awk 匹配第三个和第四个模式并将其打印在一行中

最初我已经在这个中得到了解决方案邮政

然而,这些仅适用于 2 种模式。事实证明我现在需要超过 2 个模式,可能是第 3 个模式,甚至是第 4 个模式。

我尝试通过添加从 @cas 获得的更多模式来使用以下解决方案

awk -v OFS=, '
match($0,/\<[[:digit:]]{1,2}\/[[:digit:]]{1,2}\/[[:digit:]]{4} [[:digit:]]{1,2}:[[:digit:]]{1,2}\>/,a) {dt = a[0]; next};
match($0,/3rd pattern/,b);
match($0,/INC-[[:digit:]]+-[[:digit:]]+/,a) {print a[0], dt; print b[0]}' filename.log

我得到了以下输出:

INC-210305-00000426,3/6/2021 5:19

INC-20210304-00006690,3/5/2021 5:24

只是增加了更多的空间。还有其他建议如何 grep 获取第三个或第四个模式吗?他们确实位于不同的线路。以下是输入:

unwantedtext unwantedtext unwantedtext unwantedtext 8/1/2022 6:15 (1st Pattern)

unwantedtext unwantedtext unwantedtext unwantedtext 
unwantedtext unwantedtext Report_A (3rd Pattern)
unwantedtext unwantedtext INC-220721-00007628 (2nd required pattern)
unwantedtext unwantedtext unwantedtext unwantedtext 
unwantedtext unwantedtext Report_B (4th) Pattern)

期望的输出如下:

INC-220721-00007628, 8/1/2022 6:15, Report_A

稍后我可能还需要以下输出:

INC-220721-00007628, 8/1/2022 6:15, Report_A, Report_B

我正在使用 Cygwin 和 CentOS 7 环境。

预先感谢您提供有用的解决方案。

答案1

我会使用perl而不是awk(甚至是 gawk;您使用的代码是特定于 gawk 的):

perl -l -0777 -ne '
  $time = $& if m{\b\d{1,2}/\d{1,2}/\d{4} \d{1,2}:\d{1,2}\b};
  $inc = $& if /\bINC-\d+-\d+\b/;
  @reports = /\bReport_\S+/g;
  print join ", ", $inc, $time, @reports
    if defined($time) && defined($inc)' your-file

答案2

TXR:

$ txr extract.txr input
INC-220721-00007628, 8/1/2022 6:15, Report_A, Report_B

哪里extract.txr

@(skip)@{date /[^ ]+/} @{time /[^ ]+/} (1st Pattern)
@(skip)
@(skip)@{rep1 /[^ ]+/} (3rd Pattern)
@(skip)INC-@inccode (2nd required pattern)
@(skip)
@(skip)@{rep2 /[^ ]+/} (4th) Pattern)
@(output)
INC-@inccode, @date @time, @rep1, @rep2
@(end)

我们在这里需要一点正则表达式,因为我们要匹配行尾的模式。类似于捕获文本的变量@date可能包含空格,而@{date /[^ ]+/}捕获一系列非空格字符。

由于输出只是一行,我们可以使用包含在 中的 Lisp 函数调用来替换@(output)... :@(end)@(do ...)

@(do (put-line `INC-@inccode, @date @time, @rep1, @rep2`))

答案3

使用任何 POSIX awk:

$ cat tst.awk
match($0,/([0-9]{1,2}\/){2}[0-9]{4} [0-9]{1,2}:[0-9]{1,2}/) { dt = substr($0,RSTART,RLENGTH) }
match($0,/INC(-[0-9]+){2}/) { inc  = substr($0,RSTART,RLENGTH) }
match($0,/Report_A/)        { repa = substr($0,RSTART,RLENGTH) }
match($0,/Report_B/)        { repb = substr($0,RSTART,RLENGTH) }
END { OFS=", "; print inc, dt, repa, repb }

$ awk -f tst.awk file
INC-220721-00007628, 8/1/2022 6:15, Report_A, Report_B

上面的内容将匹配目标正则表达式的中间词。您没有在问题的示例中表明这是一种可能性,但如果这是您真实数据的问题,那么只需将其更改为:

$ cat tst.awk
function set(val) {
    val = substr($0,RSTART,RLENGTH)
    gsub(/^ | $/,"",val)
    return val
}
match($0,/(^| )([0-9]{1,2}\/){2}[0-9]{4} [0-9]{1,2}:[0-9]{1,2}( |$)/) { dt = set() }
match($0,/(^| )INC(-[0-9]+){2}( |$)/) { inc  = set() }
match($0,/(^| )Report_A( |$)/)        { repa = set() }
match($0,/(^| )Report_B( |$)/)        { repb = set() }
END { OFS=", "; print inc, dt, repa, repb }

相关内容