NLTK - nltk.tokenize.RegexpTokenizer - 正则表达式未按预期工作

5

我将尝试使用RegexpTokenizer对文本进行分词。

代码:

from nltk.tokenize import RegexpTokenizer
#from nltk.tokenize import word_tokenize

line = "U.S.A Count U.S.A. Sec.of U.S. Name:Dr.John Doe J.Doe 1.11 1,000 10--20 10-20"
pattern = '[\d|\.|\,]+|[A-Z][\.|A-Z]+\b[\.]*|[\w]+|\S'
tokenizer = RegexpTokenizer(pattern)

print tokenizer.tokenize(line)
#print word_tokenize(line)

输出:

['U', '.', 'S', '.', 'A', 'Count', 'U', '.', 'S', '.', 'A', '.', 'Sec', '.', 'of', 'U', '.', 'S', '.', 'Name', ':', 'Dr', '.', 'John', 'Doe', 'J', '.', 'Doe', '1.11', '1,000', '10', '-', '-', '20', '10', '-', '20']

期望输出:

['U.S.A', 'Count', 'U.S.A.', 'Sec', '.', 'of', 'U.S.', 'Name', ':', 'Dr', '.', 'John', 'Doe', 'J.', 'Doe', '1.11', '1,000', '10', '-', '-', '20', '10', '-', '20']

为什么分词器也会分割我期望的标记"U.S.A","U.S."? 如何解决这个问题?

我的正则表达式:https://regex101.com/r/dS1jW9/1

2个回答

8
重点是你的\b是一个退格字符,你需要使用原始字符串字面值。此外,你的字符类中还有字面管道符号,这也会混淆输出结果。
这样做可以达到预期效果:
>>> pattern = r'[\d.,]+|[A-Z][.A-Z]+\b\.*|\w+|\S'
>>> tokenizer = RegexpTokenizer(pattern)
>>> print(tokenizer.tokenize(line))

['U.S.A', 'Count', 'U.S.A.', 'Sec', '.', 'of', 'U.S.', 'Name', ':', 'Dr', '.', 'John', 'Doe', 'J.', 'Doe', '1.11', '1,000', '10', '-', '-', '20', '10', '-', '20']

请注意,将单个\w放入字符类中是无意义的。此外,在字符类中不需要转义每个非单词字符(如点号),因为它们在那里大多被视为字面字符(只有^]-\需要特别注意)。

0

如果你修改了你的正则表达式

pattern = '[USA\.]{4,}|[\w]+|[\S]'

然后

pattern = '[USA\.]{4,}|[\w]+'
tokenizer = RegexpTokenizer(pattern)
print (''+str(tokenizer.tokenize(line)))

您得到了您想要的输出

['U.S.A', 'Count', 'U.S.A.', 'Sec', '.', 'of', 'U.S.', 'Name', ':', 'Dr', '.', 'John', 'Doe', 'J', '.', 'Doe', '1', '.', '11', '1', ',', '000', '10', '-', '-', '20', '10', '-', '20']

'[USA\.]{4,}|[\w]+' 也可以匹配 ............。在字符类中放入一个单独的 \w 并转义字符类内的点是没有必要的。 - Wiktor Stribiżew
同意 - 但由于测试数据已经给出(而且我太懒想不出更好的解决方案),所以这就是我提供的 :) - Tim Seed

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接