Linux:如果字符串在列表中的其他位置,则将字符串从列表中删除



我想列出字符串列表,只保留那些在列表中其他地方的列表。为了说明,我有此列表:

apple
applesauce
kiwi
mango
mangoes
mangosteen
oranges
pineapples

我想将其减少到列表中其他地方没有任何子字符串的字符串列表。因此,结果列表将是:

apple
kiwi
mango
oranges

请注意,applesaucepineapples被删除,因为apple在列表中的其他位置,并且是两个单词的子字符串。

我在这里找到了一个类似的问题,但它似乎是针对前缀的,例如ablaze, able, abler, ablest。基于该方法,我尝试使用列表的预分级副本进行以下操作,并且它只是打印了整个列表,甚至没有删除applesauce,我认为它会:

awk '$1~r && p in k { next } { k[$1]++; print; r= "^" $1; p=$1 }' fruitsorted.txt

即使它正如我预期的那样起作用,它仍然会错过我列表中的pineapple

请注意,在极端情况下,如果列表包含单个字母(或ASCII char集我猜(的所有字母,则无论列表中的其他内容如何字母/字符集。

另外,我的起始列表是未分类的。我真的不在乎是否对结果列表进行了排序,尽管这显然对sort很重要。

理想情况下,我希望有些紧凑的外壳命令/诸如grep/sort/awk之类的东西,而不是较长的perl/python/python/我已经知道如何实现的脚本。

谢谢。

update

正如下面的埃德·莫顿(Ed Morton(指出的那样,即使对列表进行排序也可能会弄乱一些基本方法,例如在下面的示例中,假设排序列表的方法可能无法删除berryplum,因为其子字符串plum之后。123所示的第二种方法处理了这种情况。

apple
applesauce
berryplum
kiwi
mango
mangoes
mangosteen
oranges
pineapples
plum

如果列表进行排序,则很简单

awk '{for(i in a)if(index($0,i))next;a[$0]}1' file
apple
kiwi
mango
oranges

基本上只是在每行的数组上循环,然后检查行中是否存在元素。如果不是这种情况,则会添加到数组。

对于未分类列表,这应该有效

awk '{for(i in a){if(index(i,$0)&&$0!=i)delete a[i];if(index($0,i))next}a[$0];next}
     END{for(i in a)print i}' file

在WordList上测试了性能。

real    0m29.932s
user    0m29.918s
sys     0m0.008s
$ awk '
   NR==FNR { fruits[$0]; next }
   {
       for (fruit in fruits) {
           if ((fruit != $0) && index($0,fruit)) {
               next
           }
        }
        final[$0]
    }
    END {
        for (fruit in final) {
            print fruit
        }
    }
' file file
mango
apple
oranges
kiwi

,如果您发现有价值的话,您可以将其全部塞到一条线上:

awk 'NR==FNR{fruits[$0];next} {for (fruit in fruits) if ((fruit != $0) && index($0,fruit)) next; final[$0]} END{for (fruit in final) print fruit}' file file

对于未分类列表,这可能会有所帮助:

awk 'NR==FNR{f1[NR]=$0;f2[$0]}
    END{
    for(i=0;i<=NR;i++){
      for(j in f2){
        if(match(f1[i],j)>=1){
            if(length(j)<length(f1[i])){
            f1[i]="nullfruit"
            }
        }
      }
    }
    for(i=0;i<=NR;i++){
         if(f1[i]!="nullfruit"){
            print f1[i];
            }
    }
    }' filename
apple
kiwi
mango
oranges

注意:可以确保存在更多 Scialtle 解决方案。

给定:

$ cat f1
apple
applesauce
berryplum
kiwi
mango
mangoes
mangosteen
oranges
pineapples
plum

您可以使用更多的循环来避免两次阅读文件或关注订单:

$ awk '{words[$1]}
     END{
        for (e in words)
            for (f in words)
                if (f!=e && index(e,f)) 
                    not[e]   
        for (e in words)
           if (!(e in not))
               print e}' f1
mango
plum
apple
oranges
kiwi

最新更新