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

如何用cat和grep批量匹配文本姓氏并统计不匹配条目数量?

问题描述

我有两个文本文件:input.txt和reference.txt,内容示例如下:

input.txt内容:

john j william
james slate
david wallace
..

reference.txt内容:

joseph william
raj kumar
william hague
david alexander

我需要检查input.txt中每行的姓氏(每行最后一个字段)是否存在于reference.txt的姓氏列表里,统计匹配和不匹配的条目数量,重点关注不匹配的计数。之前手动是逐个用grep查找参考文件里的姓氏:

cat input.txt | grep "<the_last_name>"

现在想程序化实现这个操作,拿到不匹配的计数。

方法一:用awk实现(推荐)

awk能直接处理两个文件,先把参考文件的姓氏存进数组,再遍历输入文件检查每行的姓氏是否在数组中,同时统计计数。

执行命令:

awk '
    NR == FNR { surnames[$NF] = 1; next }
    {
        if ($NF in surnames) {
            matched++
        } else {
            unmatched++
            # 要是想看到具体哪些行不匹配,取消下面这行注释
            # print $0
        }
    }
    END {
        print "匹配条目数: " matched
        print "不匹配条目数: " unmatched
    }
' reference.txt input.txt

简单说明:

  • 先处理reference.txt,把每行最后一个字段(也就是姓氏)存入surnames数组
  • 接着处理input.txt,检查每行最后一个字段是否在数组里,分别累加匹配和不匹配的数量
  • 最后在END块输出统计结果,需要查看不匹配的具体行就取消注释print $0

方法二:用grep+shell命令组合实现

先提取参考文件的姓氏生成匹配模式,再用grep匹配输入文件的行,最后计算数量:

  1. 先生成参考姓氏的正则匹配串:
REF_SURNAMES=$(awk '{print $NF}' reference.txt | sort | uniq | tr '\n' '|' | sed 's/|$//')
  1. 统计匹配和不匹配的数量:
TOTAL=$(wc -l < input.txt)
MATCHED=$(grep -E "\b($REF_SURNAMES)$" input.txt | wc -l)
UNMATCHED=$((TOTAL - MATCHED))

echo "匹配条目数: $MATCHED"
echo "不匹配条目数: $UNMATCHED"

简单说明:

  • awk '{print $NF}' reference.txt提取所有姓氏,sort | uniq去掉重复的姓氏
  • tr '\n' '|' | sed 's/|$//'把姓氏拼接成xxx|yyy|zzz的正则格式
  • grep -E "\b($REF_SURNAMES)$"匹配输入文件中以参考姓氏结尾的行(\b是单词边界,避免类似wall匹配wallace这种误判)
  • 用输入文件的总行数减去匹配数,就得到不匹配的数量

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 06:05:13