根据正则表达式描述的重复项删除行?

Remove lines based on duplicates described by regex?

假设我有这样一个文件:

apple   2018-01-01
apple cider 2018-01-05
apple cider 2017-01-06
lemon   2016-12-30
lemon   2017-12-31
lemon juice 2018-03-12
lemon pie 2018-03-30

即,它有 1 个或多个文本列,然后是日期。一些文本条目在 [不同] 日期重复。现在,我想删除这些重复项:

apple   2018-01-01
apple cider 2017-01-06
lemon   2016-12-30
lemon juice 2018-03-12
lemon pie 2018-03-30

在一栏中,可以使用this solution。但是,如果我不是在特定列中查找,而是必须通过正则表达式查找重复项怎么办? awk 可以处理吗?或者还有其他解决方法吗?

谢谢。

你可以用 awk:

awk 'BEGIN{FS="\s+2"}{a[]=2""}END{for(i in a){print i,a[i]}}' file.input | sort
apple 2018-01-01
apple cider 2017-01-06
lemon 2017-12-31
lemon juice 2018-03-12
lemon pie 2018-03-30

此解决方案将仅在重复出现时保留最后出现的值。 如果你想改变行为,你可以添加一些条件来替换值,例如,如果它是更新的。

您也可以在操作前对文件进行排序。

解释:

  • FS="\s+2 在第一列和日期之间设置字段分隔符(我假设日期以 2 开头)
  • {a[]=2""} 然后创建一个数组,其中索引是第一列,并在它们出现时分配值。
  • END{for(i in a){print i,a[i]}} 将只打印结果

假设文件已经排序,那么:

  1. 使用 revuniq:

    rev file | uniq -f1 | rev
    

    输出:

    apple   2018-01-01
    apple cider 2018-01-05
    lemon   2016-12-30
    lemon juice 2018-03-12
    lemon pie 2018-03-30
    
  2. 如果目标是删除相反的一组重复项,则添加一组 共 tac 人:

    rev file | tac | uniq -f1 | tac | rev
    

    输出:

    apple   2018-01-01
    apple cider 2017-01-06
    lemon   2017-12-31
    lemon juice 2018-03-12
    lemon pie 2018-03-30
    
  3. 如果目标是保留最早的日期:

    rev file | sed 's/ /:/' | rev | sort -t: -k 1,2gr | 
    tr : ' ' | rev | uniq -f1 | rev
    

    输出:

    apple   2018-01-01
    apple cider 2017-01-06
    lemon   2016-12-30
    lemon juice 2018-03-12
    lemon pie 2018-03-30