我想列出字符串列表,只保留那些在列表中其他地方的列表。为了说明,我有此列表:
apple
applesauce
kiwi
mango
mangoes
mangosteen
oranges
pineapples
我想将其减少到列表中其他地方没有任何子字符串的字符串列表。因此,结果列表将是:
apple
kiwi
mango
oranges
请注意,applesauce
和pineapples
被删除,因为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