【问题标题】:How to remove dupes within lines of delimited text如何删除分隔文本行中的重复项
【发布时间】:2016-02-25 17:05:30
【问题描述】:

在一行中的分隔项中删除重复项(不一定是连续的)是一种智能且简单的方法。

之前:

apple,banana,apple,cherry,cherry
delta,epsilon,delta,epsilon
apple pie,delta,delta

之后:

apple,banana,cherry
delta,epsilon
apple pie,delta

应该可以在 Mac 上运行。允许 Unicode。任何 shell 方法/语言/命令。欺骗不一定是连续的。

注意:这个问题是How to remove dupes from blocks of text 的变体——它是针对用空行分隔的文本块。

【问题讨论】:

  • 任何时候您发布“如何删除重复”问题时,您都应该在示例输入中包含一个单词是另一个单词的子字符串的情况,例如apple,pineapple 因为通常情况下,编写解决方案的人不会考虑这种情况,除非它是问题的具体部分。此外,如果可以存在 RE 元特征,例如.*? 等也包括这些,因为人们经常提出基于正则表达式而不是基于字符串的解决方案,而当可以存在 RE 元字符时,这些解决方案要正确得多。

标签: awk


【解决方案1】:
awk -F, '{ for(i=1;i<=NF;i++) if( split($0,t,$i)>2 ) sub($i",","") }1' file             
banana,apple,cherry
delta,epsilon
apple pie,delta

sed 版本:

sed -r 's/(.+)(.*),\1/\1\2,/g;s/,$//' file
apple,banana,cherry
delta,epsilon
apple pie,delta

只是代码。

【讨论】:

  • wrt awk 版本:尝试当苹果和菠萝都出现在同一行时,你会发现它会删除苹果或将菠萝截断为松树,具体取决于它们在行上的顺序.您需要添加特定于 gawk 的单词边界(仅当每个字段中的字符都是单词组成时才有效)或其他一些分隔符,然后如果字段中出现任何正则表达式元字符,它仍然会失败。它也不会以所需的顺序产生输出,因为它删除了每个字符串的第一次出现,而不是后续的。 sed 也有一些类似的问题。
【解决方案2】:
$ awk 'BEGIN { FS=OFS="," }
{
    delete seen
    sep=""
    for (i=1;i<=NF;i++) {
        if (!seen[$i]++) {
            printf "%s%s", sep, $i
            sep = OFS
        }
    }
    print ""
}' file
apple,banana,cherry
delta,epsilon
apple pie,delta

【讨论】:

  • 没有单行吗?我想它可能是通过 tr 之前/之后管道的单线。
  • Ed Morton 脚本在一行中 awk -v OFS="," -F"," '{ delete seen; sep=""; for(i=1;i&lt;=NF;i++){if (!seen[$i]++) {printf "%s%s", sep, $i; sep = OFS} print ""}' file
  • 您总是可以将任何 awk 脚本塞到一行中,方法是在每行末尾添加分号,而不是以 {} 结尾,但根据我的经验,这会造成难以辨认零收益的混乱。
  • 问题在于易于维护和修改。 Ed 对这个问题的变体 (stackoverflow.com/questions/35618467/…) 的解决方案非常优雅,为了我的目的,我将这种分隔格式(使用逗号)转换为/从每行一个格式(使用 tr 和/或 sed)。这会产生一个非常容易阅读的管道单层。
  • 如果你打算加入 trs 和 seds 只是为了让它保持在一条线上,你可能会更好地使用不太清晰(比上面的)和 gawk 特定的:awk 'BEGIN{RS="[,\n]"} !seen[$0]++{r=r s $0; s=","} RT=="\n"{print r; r=s=""; delete seen}' file
猜你喜欢
  • 2017-12-10
  • 1970-01-01
  • 2014-05-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-02
  • 1970-01-01
  • 2021-05-18
相关资源
最近更新 更多