使用 awk 只打印匹配后的下一行

使用 awk 只打印匹配后的下一行

grep我有一个命令,可以使用不同的工具(如、awk和)与多个管道匹配后直接打印该行tail。这可行,但感觉有点混乱,并且使用多个管道来完成此任务。是否可以仅使用这些工具之一通过一个命令来完成此操作?文件末尾还有一行空格。

文件内容:

10:28:48  2022-09-15T15:28:36Z:    Creating tar ball for build artifacts
--
10:28:53  --> Build complete: Artifacts were created:
file: build-1.tar.gz

命令

grep -A1 "Artifacts were created:" $file | tail -n1 | awk '{print $2}'

结果

build-1.tar.gz

这在技术上是可行的,但看起来有点草率。

答案1

请尝试:

awk '/Artifacts were created:/{p=1} NF{out=$2}  END{if(p==1){print out}}' infile

尽管您提供的管道正在提取匹配项之后的行的第二个字段,而不是最后一个字段。这可以转换为对 awk 的一次调用:

awk '
      # Have we found the match?
      /Artifacts were created:/{ found=1 ; next }
      
      # if a match has been found, print and exit
      found == 1 { print $2; exit }

    ' "$file"

答案2

如果sed是一个选项

$ sed -En '/Artifacts were created:/{n;s/[^ ]* (.*)/\1/p}' <<< "$file"
build-1.tar.gz

答案3

原来的要求要求匹配后最后一个非空白行的值。在这里,当您找到匹配触发器时,设置一个标志。设置标志后,等待文件末尾,然后打印我们捕获的最后一项:

awk '
    # Set the flag on match
    /Artifacts were created/ { flag++ }

    # Capture second field of a line that is not just whitespace
    NF { lastitem = $2 }

    # At the end, maybe print the last captured item
    END { if (flag) { print lastitem } }
' "$file"

在某些版本中,awk您可能可以引用子句$2中的最后一个END。在这里,我更喜欢一种更直接的方法,在我们浏览文件时捕获最新的行项目。


更新后的要求要求紧接着匹配后的行中提供值。这要简单得多,而且可能更快,因为文件不一定需要完整处理:

awk '
    # Output second field of line immediately following the flag being set
    flag && NF { print $2; exit }

    # Set the flag on match
    /Artifacts were created/ { flag++ }

' "$file"

答案4

使用(以前称为 Perl_6)

~$ raku -e 'put $<>.words[1] if m{ "Artifacts were created:" \n <( \N* } for lines.join: "\n";'  file

#OR

~$ raku -e 'put $0.words[1] if m{ "Artifacts were created:" \n (\N*) } for lines.join: "\n";'  file  

如果OP愿意考虑Perl系列编程语言,Raku是一个不错的选择。上面,输入文件按行读入,并用\n换行符连接。识别目标"Artifacts were created:" \n,然后寻找匹配。

在第一个示例中,Raku 的捕获标记<( … )>用于从匹配对象中删除“Artifacts...”行,并且.words[1]捕获的第二个空格分隔字段put使用$<>(或同义$/)匹配变量(受if条件限制)输出)。实际上,对于这个问题只<(需要一个捕获标记。

在第二个示例中,括号用于将匹配的一部分捕获到 match-variable 中,$<>.[0]该 match-variable 与 match-variable 相同,$/.[0]而 match-variable 与 相同$0。捕获的第二.words[1]个空格分隔字段$0受条件put限制if

输入示例:

10:28:48  2022-09-15T15:28:36Z:    Creating tar ball for build artifacts
--
10:28:53  --> Build complete: Artifacts were created:
file: build-1.tar.gz

示例输出:

build-1.tar.gz

Raku 中确实有相当多的内置字符类,因此[\N* \n]可以将特征模式(零个或多个非换行符后跟换行符)复制为许多其他模式(例如[\S* \s][\d* \D]等)。

https://docs.raku.org/language/regexes
https://raku.org

相关内容