Разделение строки python по символам при сохранении встроенных тегов без изменений

#python #regex #nlp #data-cleaning

#python #регулярное выражение #nlp #очистка данных

Вопрос:

Я пытаюсь создать пользовательский токенизатор на python, который работает со встроенными тегами. Цель состоит в том, чтобы ввести строку следующим образом:

 'This is *tag1* a test *tag2*.'
 

и пусть он выводит список, разделенный тегом и символом:

 ['T', 'h', 'i', 's', ' ', 'i', 's', ' ', '*tag1*', ' ',  'a', ' ', 't', 'e', 's', 't', ' ', '*tag2*', '.']
 

без тегов я бы просто использовал list() , и я думаю, что нашел решение для работы с одним типом тега, но их несколько. Существуют также другие многосимвольные сегменты, такие как многоточия, которые должны быть закодированы как единый объект.
Одна вещь, которую я пробовал, — это замена тега одним неиспользуемым символом на регулярное выражение, а затем использование list() в строке:

 text = 'This is *tag1* a test *tag2*.'
tidx = re.match(r'*.*?*', text)
text = re.sub(r'*.*?*', r'#', text)
text = list(text)
 

затем я бы повторил его и заменил ‘#’ извлеченными тегами, но у меня есть несколько разных функций, которые я пытаюсь извлечь, и повторение процесса несколько раз с разными символами-заполнителями перед разделением строки кажется плохой практикой. Есть ли более простой способ сделать что-то подобное? Я все еще новичок в этом, поэтому есть еще много распространенных методов, о которых я не знаю. Я думаю, я также могу использовать более крупное регулярное выражение, которое охватывает все функции, которые я пытаюсь извлечь, но оно все равно кажется хакерским, и я бы предпочел использовать что-то более модульное, которое можно использовать для поиска других функций, не записывая каждый раз новое выражение.

Комментарии:

1. взгляните на лексические сканеры, напишите грамматику вашего текста, и он проанализирует ее для вас, или напишите свой собственный конечный автомат

Ответ №1:

Вы можете использовать следующее регулярное выражение с re.findall :

 *[^*]**|.
 

Смотрите демонстрацию регулярных выражений. Флаг re.S or re.DOTALL можно использовать с этим шаблоном, чтобы . он также мог сопоставлять символы разрыва строки, которым он не соответствует по умолчанию.

Подробные сведения

  • *[^*]** * символ, за которым следует ноль или более символов, отличных от * , а затем *
  • | — или
  • . — любой символ (с re.S ).

Смотрите демонстрацию Python:

 import re
s = 'This is *tag1* a test *tag2*.'
print( re.findall(r'*[^*]**|.', s, re.S) )
# => ['T', 'h', 'i', 's', ' ', 'i', 's', ' ', '*tag1*', ' ', 'a', ' ', 't', 'e', 's', 't', ' ', '*tag2*', '.']
 

Комментарии:

1. Кажется, это работает хорошо. Вместо того, чтобы расширять выражение для работы с эллипсами и другими функциями, я просто использовал еще пару функций регулярных выражений, чтобы преобразовать все это в теги по схеме звездочки, так что все должно работать нормально.

Ответ №2:

Я не уверен точно, что было бы лучше для вас, но вы должны иметь возможность использовать метод split() или метод .format(), представленный ниже, чтобы получить то, что вы хотите.

 # you can use this to get what you need
txt = 'This is *tag1* a test *tag2*.'
x = txt.split("*") #Splits up at *
x = txt.split() #Splits all the words up at the spaces
print(x)

# also, you may be looking for something like this to format a string
mystring = 'This is {} a test {}.'.format('*tag1*', '*tag2*')
print(mystring)


# using split to get ['T', 'h', 'i', 's', ' ', 'i', 's', ' ', '*tag1*', ' ',  'a', ' ', 't', 'e', 's', 't', ' ', '*tag2*', '.']
txt = 'This is *tag1* a test *tag2*.'
split = txt.split("*") #Splits up at *

finallist = [] # initialize the list
for string in split:

    # print(string)
    if string == '*tag1*':
        finallist.append(string)
        # pass
    elif string == '*tag2*.':
        finallist.append(string)

    else:
        for x in range(len(string)):
            letter = string[x]
            finallist.append(letter)

print(finallist)