![查找指定行上包含(不包含)文本模式的文件](https://linux22.com/image/144951/%E6%9F%A5%E6%89%BE%E6%8C%87%E5%AE%9A%E8%A1%8C%E4%B8%8A%E5%8C%85%E5%90%AB%EF%BC%88%E4%B8%8D%E5%8C%85%E5%90%AB%EF%BC%89%E6%96%87%E6%9C%AC%E6%A8%A1%E5%BC%8F%E7%9A%84%E6%96%87%E4%BB%B6.png)
我正在尝试搜索一组文本文件并返回以下文件的名称在指定行上包含文本模式或不包含指定的文本。就我而言,我需要返回最后一行不包含文本模式的文件的文件名。
文件1.txt
line1 abc
line2 必须有
文件2.txt
line1 必须让
line2 返回我
函数/命令在传递“必须有”时,应仅返回 file2.txt,因为它的最后一行不包含“必须有”。
答案1
要检查当前目录中每个文件最后一行的内容,请使用tail
和grep
:
for file in *.txt
do
tail -1 -- "$file" | grep -q "must have" || printf '%s\n' "$file"
done
这假设您的文本文件的命名以.txt
;结尾。根据需要调整该通配符。抓取tail -1
文件的最后一行(向后查找,这比可能向前读取文件更有效);然后通过管道传送到该行以grep
查找所需的文本。 grep 的标志-q
告诉它对其工作保持安静,只需相应地设置返回代码即可。如果 grep 这样做不是找到匹配项,然后||
“或”交替告诉 shell 执行printf
,打印文件名。
您可以将该代码放入脚本或函数中:
lastlinehas() {
for file in *.txt
do
tail -1 -- "$file" | grep -q "$1" || printf '%s\n' "$file"
done
}
答案2
使用 GNU awk
:
$ awk 'ENDFILE { if ($0 !~ /must have/) print FILENAME }' file2.txt file1.txt
file2.txt
这使用一个ENDFILE
块来根据正则表达式测试当前内容$0
(我们刚刚到达末尾的文件的最后一行)must have
。如果没有匹配,则打印文件名。
该ENDFILE
块在 BSDawk
或mawk
.
使用标准awk
:
for fname in *.txt; do
awk 'END { if ($0 !~ /must have/) print FILENAME }' "$fname"
done
这与 GNUawk
解决方案类似,但awk
为每个文件调用一次。