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

使用Awk删除最早重复行并保留最新重复行,同时删除被删重复行的上一行

嗨,我来帮你解决这个问题!你需要保留每个命令最后出现的条目(包括对应的时间戳行),删除更早的重复项,这和常见的保留最早重复项的需求正好相反,我们可以用 Awk 来实现这个逻辑。

情况1:每行格式为 #时间戳 命令(如你的输入示例)

如果你的输入每行是时间戳加命令的组合,比如:

#1655636921 cd
#1655636926 history
#1655637510 history
#1655637934 ls
#1655637934 ls
#1655638524 cd
#1655638927 ls
#1655638928 history

可以用这个 Awk 脚本,它会保留每个命令最后出现的行,并且保持最后出现的顺序:

awk '
{
    # 提取命令部分(时间戳后的内容)
    cmd = substr($0, index($0, " ") + 1)
    
    # 如果命令已存在,从顺序列表中移除旧条目
    if (cmd in latest) {
        for (i = 1; i <= count; i++) {
            if (order[i] == cmd) {
                for (j = i; j < count; j++) {
                    order[j] = order[j+1]
                }
                count--
                break
            }
        }
    }
    # 将命令添加到顺序末尾,更新最新行记录
    order[++count] = cmd
    latest[cmd] = $0
}
END {
    # 按最后出现的顺序输出结果
    for (i = 1; i <= count; i++) {
        print latest[order[i]]
    }
}
' your_input_file.txt

脚本解释:

  • substr($0, index($0, " ") + 1):从每行中提取命令部分(比如从 #1655636921 cd 中取出 cd)
  • latest[cmd] = $0:用数组记录每个命令对应的最新行,遇到重复命令就覆盖旧值
  • order 数组用来维护命令最后出现的顺序:如果命令已经存在,就把它从原来的位置移到数组末尾,确保输出顺序和最后出现的先后一致
  • END 块遍历顺序数组,输出对应的最新行,正好得到你想要的结果。

情况2:输入是成对行(奇数行是时间戳,偶数行是命令)

如果你的输入是奇数行仅为时间戳(#xxxxxx),偶数行是命令,比如:

#1655636921
cd
#1655636926
history
#1655637510
history
#1655637934
ls
#1655637934
ls
#1655638524
cd
#1655638927
ls
#1655638928
history

可以用这个脚本,它会成对删除旧的重复项:

awk '
# 处理奇数行(时间戳行)
NR % 2 == 1 {
    timestamp = $0
    next
}
# 处理偶数行(命令行)
{
    cmd = $0
    # 如果命令已存在,删除旧的时间戳和命令行记录
    if (cmd in cmd_map) {
        delete lines[cmd_map[cmd] - 1]
        delete lines[cmd_map[cmd]]
    }
    # 更新命令对应的最新行号
    cmd_map[cmd] = NR
    # 保存当前时间戳和命令行
    lines[NR - 1] = timestamp
    lines[NR] = cmd
}
END {
    # 按行号顺序输出保留的行
    for (i = 1; i <= NR; i++) {
        if (i in lines) {
            print lines[i]
        }
    }
}
' your_input_file.txt

脚本解释:

  • NR % 2 == 1:识别奇数行,保存时间戳后直接处理下一行(命令行)
  • 遇到重复命令时,删除之前保存的对应时间戳行和命令行
  • cmd_map 记录每个命令对应的最新命令行行号,lines 数组保存所有需要保留的行
  • END 块按行号顺序输出,保证结果的顺序正确

和你提到的 awk '!visited[$0]++' 的区别

你说的这个脚本是通过标记每行是否已访问,第一次出现时保留,后续重复行跳过,所以它保留的是最早的重复行。而我们的脚本是通过覆盖最新记录或删除旧记录的方式,实现保留最新的重复行,正好满足你的需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 00:27:38