我在Python中使用以下正则表达式来保留不包含非字母字符的单词:
(?<!\S)[A-Za-z]+(?!\S)|(?<!\S)[A-Za-z]+(?=:(?!\S))
问题是这个正则表达式没有保留我想保留的单词,如下所示:
Company,
months.
third-party
换句话说,我想保留一个逗号,一个点或两个单词之间的短语。
关于如何实现这一点的任何想法?
我尝试为点添加类似|(?<!\S)[A-Za-z]+(?=\.(?!\S))
的内容,但似乎没有效果。
谢谢!
编辑:
应该匹配这些:
On-line
. These
maintenance,
other.
. Our
Google
不应该匹配这些:
MFgwCgYEVQgBAQICAf8DSgAwRwJAW2sNKK9AVtBzYZmr6aGjlWyK3XmZv3dTINen
NY7xtb92dCTfvEjdmkDrUw==
$As_Of_12_31_20104206http://www.sec.gov/CIK0001393311instant2010-12-31T00:00:000001-01-01T00:00:00falsefalseArlington/S.Cooper
-Publisher
gaap_RealEstateAndAccumulatedDepreciationCostsCapitalizedSubsequentToAcquisitionCarryingCostsus
目前我正在使用以下python代码逐行读取文本文件:
find_words = re.compile(r'(?<!\S)[A-Za-z]+(?!\S)|(?<!\S)[A-Za-z]+(?=:(?!\S))').findall
然后我打开文本文件
contents = open("test.txt","r")
我在内容中逐行搜索单词:
if find_words(line.lower()) != []: lineWords=find_words(line.lower())
print "The words in this line are: ", lineWords
以下列方式使用一些单词列表:
wanted1 = set(find_words(open('word_list_1.csv').read().lower()))
wanted2 = set(find_words(open('word_list_2.csv').read().lower()))
negators = set(find_words(open('word_list_3.csv').read().lower()))
我首先要从.txt文件中获取有效单词,然后检查这些单词是否属于单词列表。这两个步骤是独立的。
答案 0 :(得分:1)
这不是正则表达式任务,因为你无法用regext检测单词。你必须有一本字典来检查你的单词。
所以我建议使用正则表达式将字符串拆分为非字母字符,并检查字典中是否存在所有项目。例如:
import re
words=re.split(r'\S+',my_string)
print all(i in my_dict for i in words if i)
作为替代原生,您可以使用nltk.corups
as your dictionary:
from nltk.corpus import wordnet
words=re.split(r'\S+',my_string)
if all(wordnet.synsets(word) for i in words if i):
#do stuff
但是如果您想使用自己的单词列表,则需要更改正则表达式,因为它不正确而是使用前面的re.split
:
all_words = wanted1|wanted2|negators
with open("test.txt","r") as f :
for line in f :
for word in line.split():
words=re.split(r'\S+',word)
if all(i in all_words for i in words if i):
print word
答案 1 :(得分:1)
您可以使用\b
来检测单词的边界,而不是使用各种复杂的环视。这样,您可以使用例如\b[a-zA-Z]+(?:-[a-zA-Z]+)*\b
示例:
>>> p = r"\b[a-zA-Z]+(?:-[a-zA-Z]+)*\b"
>>> text = "This is some example text, with some multi-hyphen-words and invalid42 words in it."
>>> re.findall(p, text)
['This', 'is', 'some', 'example', 'text', 'with', 'some', 'multi-hyphen-words', 'and', 'words', 'in', 'it']
更新:似乎这样做效果不好,因为它还会检测来自网址的片段,例如:来自www
的{{1}},sec
和gov
。
相反,您可以尝试使用这种变体,使用环绕声明确说明“法律”和“法律”。字符:
http://www.sec.gov
让我们剖析这个正则表达式:
r"""(?<![^\s("])[a-zA-Z]+(?:[-'][a-zA-Z]+)*(?=[\s.,:;!?")])"""
- 后面断言该单词前面有空格,引号或parens,但是例如不是一个数字(使用双重否定而不是正面的后视,所以第一个单词也匹配)(?<![^\s("])
- [a-zA-Z]+
- 在(?:[-'][a-zA-Z]+)*
或'
-
- 前瞻断言该单词后跟空格,标点符号,引号或parens 答案 2 :(得分:1)
我提出这个正则表达式:
find_words = re.compile(r'(?:(?<=[^\w./-])|(?<=^))[A-Za-z]+(?:-[A-Za-z]+)*(?=\W|$)').findall
我最初的正则表达式中有3个部分我改变了:
中间部分:
[A-Za-z]+(?:-[A-Za-z]+)*
这允许带连字符的单词。
最后一部分:
(?=\W|$)
这有点类似于(?!\S)
,除了它允许字符不是像标点符号那样的空格。所以会发生这种情况,如果在匹配的单词之后,该行结束,或者存在非单词字符,那么这将允许匹配,换句话说,没有字母或数字或下划线(如果你不是这样的话)希望word_
与word
匹配,然后您必须将\W
更改为[a-zA-Z0-9]
)。
第一部分(可能是最复杂的):
(?:(?<=[^\w./-])|(?<=^))
它由两部分组成,它们匹配(?<=[^\w./-])
或(?<=^)
。如果该行在要匹配的单词之前开始,则第二个允许匹配。我们不能使用(?<=[^\w./-]|^)
,因为来自re
的python的lookbehind不能具有可变宽度([^\w./-]
的长度为1且^
的长度为0)。
(?<=[^\w./-])
允许匹配。
如果细分,我认为小部件相当简单,但如果您想要更详细的内容,我可以提供更多细节。