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]
等)。