Grep(a.txt - En单词列表,b.txt - 每行一个字符串)问:b.txt中的字符串是否仅由单词构成?

时间:2014-04-03 08:30:42

标签: string bash grep

我有一个英文单词列表(每行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

2 个答案:

答案 0 :(得分:1)

由于您的问题未得到详细说明,或许这个答案可以帮助您解决问题:

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

这将只传递除了这些单词的连接之外的行。但它也会传递像'appleapplepieapplepiepieapple'这样的东西。再说一次,我不知道这是不是你想要的。

鉴于你在问题中的最新解释,我会提出另一种方法(因为用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,然后在您的文本文件中留下单词potapota不是一个可以删除的词。

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

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

答案 1 :(得分:1)

我也会将此作为答案发布,因为我认为这是您具体问题的正确答案。

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

您面临两个问题:

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

  2. 尽管如此,你仍然试图通过编译所有可能排列的列表来自己构建一个复合词列表,因为你的词汇表的大小(以及由此导致的内存问题),你不能轻易做到这一点。您很可能必须将您的文字存储在更复杂的数据结构中,例如一棵树,并通过遍历在shell脚本中无法实现的树来动态构建排列。

  3. 由于这些要点和您的实际问题是“这可以通过grep完成吗?”答案是否定的,这是不可能的。