Python заменяет одинарные кавычки, кроме апострофов - PullRequest
0 голосов
/ 09 июня 2018

Я выполняю следующие операции со списками слов.Я читаю строки из текстового файла Project Gutenberg, разбиваю каждую строку на пробелы, выполняю общую замену знаков препинания, а затем печатаю каждое слово и тег пунктуации на отдельной строке для дальнейшей обработки позже.Я не уверен, как заменить каждую цитату тегом или исключая все апострофы.Мой текущий метод состоит в том, чтобы использовать скомпилированное регулярное выражение:

apo = re.compile("[A-Za-z]'[A-Za-z]")

и выполнить следующую операцию:

if "'" in word and !apo.search(word):
    word = word.replace("'","\n<singlequote>")

, но это игнорирует случаи, когда одна кавычка используется вокруг слова с апострофом,Это также не указывает мне, является ли одиночная кавычка примыкающей к началу слова конца слова.

Пример ввода:

don't
'George
ma'am
end.'
didn't.'
'Won't

Пример вывода (после обработки и печатив файл):

don't
<opensingle>
George
ma'am
end
<period>
<closesingle>
didn't
<period>
<closesingle>
<opensingle>
Won't

У меня есть еще один вопрос в связи с этой задачей: так как разграничение <opensingle> против <closesingle> кажется довольно трудным, было бы разумнее выполнять замены, такие как

word = word.replace('.','\n<period>')
word = word.replace(',','\n<comma>')

после выполнения операции замены?

Ответы [ 3 ]

0 голосов
/ 09 июня 2018

Что вам действительно нужно, чтобы правильно заменить начало и конец ', это regex .Чтобы соответствовать им, вы должны использовать:

  • ^' для начала ' ( opensingle ),
  • '$ для окончания ' ( closesingle ).

К сожалению, метод replace не поддерживает регулярные выражения, поэтому вместо него следует использовать re.sub.

Ниже приведен пример программы,печать желаемого результата (в Python 3 ):

import re
str = "don't 'George ma'am end.' didn't.' 'Won't"
words = str.split(" ")
for word in words:
    word = re.sub(r"^'", '<opensingle>\n', word)
    word = re.sub(r"'$", '\n<closesingle>', word)
    word = word.replace('.', '\n<period>')
    word = word.replace(',', '\n<comma>')
    print(word)
0 голосов
/ 09 июня 2018

Я думаю, что это может быть полезно с помощью прогнозных или косвенных ссылок.Ссылка на Python - https://docs.python.org/3/library/re.html,, а один общий сайт регулярных выражений, на который я часто ссылаюсь, - https://www.regular -expressions.info / lookaround.html .

Ваши данные:

words = ["don't",
         "'George",
         "ma'am",
         "end.'",
         "didn't.'",
         "'Won't",]

А теперь я определю кортеж с регулярными выражениями и их заменами.

In [230]: apo = (
    (re.compile("(?<=[A-Za-z])'(?=[A-Za-z])"), "<apostrophe>",),
    (re.compile("(?<![A-Za-z])'(?=[A-Za-z])"), "<opensingle>",),
    (re.compile("(?<=[.A-Za-z])'(?![A-Za-z])"), "<closesingle>", ),
    (re.compile("(?<=[A-Za-z])\\.(?![A-Za-z])"), "<period>",),
)
     ...:      ...:      ...:      ...:      ...:      ...: 
In [231]: words = ["don't",
         "'George",
         "ma'am",
         "end.'",
         "didn't.'",
         "'Won't",]
     ...:      ...:      ...:      ...:      ...:      ...: 
In [232]: reduce(lambda w2,x: [ x[0].sub(x[1], w) for w in w2], apo, words)
Out[232]: 
['don<apostrophe>t',
 '<opensingle>George',
 'ma<apostrophe>am',
 'end<period><closesingle>',
 'didn<apostrophe>t<period><closesingle>',
 '<opensingle>Won<apostrophe>t']

Вот что происходит с регулярными выражениями:

  1. (?<=[A-Za-z]) lookbehind , означающее только совпадение (но не потребляет ), если предыдущий символ представляет собой букву.
  2. (?=[A-Za-z]) является lookahead (по-прежнему не потреблять), если следующий символ представляет собой букву.
  3. (?<![A-Za-z]) - это негативный вид сзади , то есть, если перед ним стоит буква, она не будет совпадать.
  4. (?![A-Za-z]) является негативным прогнозом .

Обратите внимание, что я добавил . чек в <closesingle>, и порядок в apo имеет значение,потому что вы можете заменить . на <period> ...

Это работало с отдельными словами, но должно работать и с предложениями.

In [233]: onelong = """
don't
'George
ma'am
end.'
didn't.'
'Won't
"""
     ...:      ...:      ...:      ...:      ...:      ...:      ...: 
In [235]: print(
    reduce(lambda sentence,x: x[0].sub(x[1], sentence), apo, onelong)
)

     ...:      ...: 
don<apostrophe>t
<opensingle>George
ma<apostrophe>am
end<period><closesingle>
didn<apostrophe>t<period><closesingle>
<opensingle>Won<apostrophe>t

(Использование reduce для облегчения применения регулярного выражения .sub к словам / строкам и последующего сохранения этого вывода для следующего регулярного выражения .sub и т. Д.)

0 голосов
/ 09 июня 2018

Я предлагаю поработать с умом здесь: используйте nltk или другой инструментарий НЛП.

Токенизируйте слова , например:

import nltk
sentence = """At eight o'clock on Thursday morning
Arthur didn't feel very good."""
tokens = nltk.word_tokenize(sentence)

Вам может не понравиться тот факт, что сокращения как не разделены.На самом деле, это ожидаемое поведение.См. Выпуск 401 .

Тем не менее, TweetTokenizer может помочь с этим:

from nltk.tokenize import tknzr = TweetTokenizer()
tknzr.tokenize("The code didn't work!")

Если это станет более сложным, RegexpTokenizer может быть полезен:

from nltk.tokenize import RegexpTokenizer
s = "Good muffins cost $3.88\nin New York.  Please don't buy me\njust one of them."
tokenizer = RegexpTokenizer('\w+|\$[\d\.]+|\S+')
tokenizer.tokenize(s)

Тогда это должно быть намного прощеправильно комментируйте токенизированные слова.

Дополнительные ссылки:

...