Grep (a.txt - En 单词列表,b.txt - 每行一个字符串) Q:来自 b 的字符串.txt是否仅由单词



>我有一个包含英语单词的列表(每行 1 个,大约 100.000)-> a.txt 和 b.txt 包含字符串(大约 50.000 行,每行一个字符串,可以包含纯单词、单词+东西、垃圾)。我想知道 b.txt 中的哪些字符串仅包含英语单词(没有任何额外的字符)。

我可以用grep做到这一点吗?

例:

a.txt

apple
pie

b.txt

applepie
applebs
bspie
bsabcbs

输出:

c.txt

applepie

由于您的问题未被指定,也许这个答案可以帮助您在黑暗中澄清您的问题:

c='cat b.txt'
while IFS='' read -e line
do
  c="$c | grep '$line'"
done < a.txt
eval "$c" > c.txt

但这也会匹配像this is my apply on a pie这样的台词. 我不知道这是否是你想要的。

这是另一个尝试:

re=''
while IFS='' read -e line
do
  re="$re${re:+|}$line"
done < a.txt
grep -E "^($re)*$" b.txt > c.txt

这将只允许通过只有这些单词串联的行。 但它也会让"苹果派苹果"这样的东西通过。 同样,我不知道这是否是你想要的。

鉴于您对问题的最新解释,我会提出另一种方法(因为从 100000+ 字中构建这样的列表是行不通的)。

对于如此多的单词,一种工作方法可能是从文本中删除所有已识别的单词,并查看在此过程中清空了哪些行。 这可以轻松地以迭代方式完成,而不会爆炸内存使用量或其他资源。 不过,这需要时间。

cp b.txt inprogress.txt
while IFS='' read -e line
do
  sed -i "s/$line//g" inprogress.txt
done < a.txt
for lineNumber in $(grep -n '^$' inprogress.txt | sed 's/://')
do
  sed -n "${lineNumber}p" b.txt
done
rm inprogress.txt

但这仍然不能真正解决您的问题;考虑一下,如果您的列表中有单词topotato,并且首先删除to,那么这将在您的文本文件中留下一个单词pota,并且pota不是随后将被删除的单词。

您可以通过按单词长度(最长单词优先)对单词文件进行排序来解决这个问题,但在某些复合词的情况下,这仍然是有问题的,例如 redartred + art),但dart将首先被删除,因此re将保留。 如果这不在您的单词列表中,您将无法识别该单词。

实际上,您的问题是逻辑编程和自然语言处理的问题之一,可能不适合SO。 你应该看看Prolog语言,它是围绕你的问题而设计的。

我也会将其作为答案发布,因为我觉得这是您特定问题的正确答案。

您的要求是根据包含英语单词列表的单词列表(a.txt)在文件(b.txt)中查找非英语单词。根据您问题中的示例,所述单词列表不包含复合词(例如 applepie ),但您仍然希望根据单词列表中的单词将文件与复合词进行匹配(例如 applepie)。

您面临两个问题:

  1. 并非a.txt中的每个单词排列都是有效的英语复合词,因此仅基于此您的问题已经无法解决。

  2. 尽管如此,如果你试图通过编译所有可能的排列列表来自己建立一个复合词列表,由于你的单词列表的大小(以及由此产生的记忆问题),你不能轻易做到这一点。您很可能必须将单词存储在更复杂的数据结构中,例如树,并通过遍历树来动态构建排列,这在 shell 脚本中是不可行的。

由于这些要点和你的实际问题是"这可以用grep完成吗?"答案是否定的,这是不可能的。

最新更新