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

标签 linux bash awk grep substring

我想获取一个字符串列表,并仅保留列表中其他地方没有子字符串的字符串。为了说明这一点,我有这个列表:

apple
applesauce
kiwi
mango
mangoes
mangosteen
oranges
pineapples

我想将其缩减为一个字符串列表,该列表中的其他位置没有任何子字符串。因此,结果列表将是:

apple
kiwi
mango
oranges

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

我发现了类似的问题here但它似乎专门针对前缀,例如闪耀,能干,能干,最能干。基于该方法,我对列表的预排序副本尝试了以下操作,它只是打印了整个列表,甚至没有删除我认为会删除的 applesauce :

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

即使它按照我的预期工作,它仍然会错过我的列表中的pineapple

请注意,在极端情况下,如果列表包含字母表中的所有字母(我猜是 ASCII 字符集),每个字母都在单独的行上,那么无论列表中还有什么,输出都将是字母/字符集。

此外,我的起始列表未排序。我并不关心结果列表是否已排序,尽管这对于 sort 来说显然是微不足道的。

理想情况下,我想要一个稍微紧凑的 shell 命令/诸如 grep/sort/awk 之类的东西序列,而不是更长的 Perl/Python/任何我已经知道如何实现的脚本。

谢谢。

更新

正如埃德·莫顿(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

关于Linux:如果字符串在列表中其他位置有子字符串,则从列表中删除字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44722588/

相关文章:

regex - "partial grep"加快grep速度?

mysql - 无法通过套接字 '/var/run/mysqld/mysqld.sock' 连接到本地 MySQL 服务器。

linux - 如何转义 sed 输入文件

linux - grep while read 行替代

linux - 重复从一行中提取组名?

c - 目标和模块的内核版本

linux - 如何删除第二列中的值出现特定次数的文件的行?

bash - ffmpeg 从大型视频 bash 中选择子剪辑并创建输出文件名

linux - 在bash中解析conf文件

regex - 替换字符串之间的文本(例如使用 sed)