You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用grep匹配内容的最后一次出现而非首次

如何提取每个文件中匹配文本的最后一次出现

刚好碰到过类似的需求!你现在是想遍历ibrav8_c11mc12/下的所有文件,每个文件只保留最后一行包含!的内容,而不是把所有匹配行都列出来对吧?下面给你几个实用的解决方案:


方法1:用循环结合tac+grep实现

tac命令会把文件内容倒序输出,所以我们可以用它快速定位到原文件的最后一个匹配行:

for file in ibrav8_c11mc12/*; do
  # 只处理普通文件,跳过目录等非文件条目
  if [ -f "$file" ]; then
    # 倒读文件,取第一个匹配行(即原文件的最后一个匹配),再加上文件名前缀
    tac "$file" | grep -m1 "!" | sed "s/^/$file:/"
  fi
done

这里的grep -m1表示只取第一个匹配结果,配合tac就刚好拿到原文件的最后一个匹配行,最后用sed给行内容加上文件名,和grep默认的输出格式完全一致。


方法2:用awk一次性处理,更高效

如果文件数量较多,用awk可以避免循环,直接批量处理所有文件,效率更高:

awk '/!/ { last_match = FILENAME ":" $0 } ENDFILE { print last_match }' ibrav8_c11mc12/*

原理很简单:

  • 每匹配到一行带!的内容,就把「文件名:行内容」存到last_match变量里,后续匹配会自动覆盖之前的内容
  • 当每个文件处理完成时(ENDFILE事件),打印最后一次保存的last_match,也就是该文件的最后一个匹配行

这个方法输出的格式和你原来的grep完全一致,而且不用单独处理目录,awk会自动跳过非文件的条目。


额外适配提示

如果你的系统是macOS(默认是BSD版本的awk),ENDFILE是GNU awk的特性,可以换成下面的写法,效果完全相同:

awk 'FNR == 1 { if (last_match) print last_match; last_match = "" } /!/ { last_match = FILENAME ":" $0 } END { print last_match }' ibrav8_c11mc12/*

内容的提问来源于stack exchange,提问作者Daniel Marchand

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 03:27:15