Разделить регулярным выражением, но с первым символом разделителя - PullRequest
0 голосов
/ 22 апреля 2020

У меня есть такое регулярное выражение: "[a-z|A-Z|0-9]: ", которое будет соответствовать одному алфавиту c символу, двоеточию и пробелу. Интересно, как разбить строку, но оставить символ alphanumeri c в первом результате разбиения. Я не могу изменить регулярное выражение, потому что в некоторых случаях строка будет иметь специальный символ перед двоеточием и пробелом.

Пример:

line = re.split("[a-z|A-Z|0-9]: ", "A: ") # Result: ['A', '']
line = re.split("[a-z|A-Z|0-9]: ", ":: )5: ") # Result: [':: )5', '']
line = re.split("[a-z|A-Z|0-9]: ", "Delicious :): I want to eat this again") # Result: ['Delicious :)', 'I want to eat this again']

Обновление: На самом деле, мой Проблема заключается в том, чтобы отделиться от файла обзора. Предположим, у меня есть файл, в котором каждая строка имеет такой шаблон: [title]: [review]. Я хочу получить заголовок и рецензию, но некоторые из заголовков имеют специальный символ перед двоеточием и пробелом, и я не хочу их сопоставлять. Тем не менее, кажется, что символ перед двоеточием и пробелом, который я хочу сопоставить, по-видимому, alphanumeri c.

Ответы [ 2 ]

0 голосов
/ 22 апреля 2020

Вы можете разделить, используя отрицательный вид сзади, с одним двоеточием или использовать класс символов [:)], где вы можете указать, какие символы не должны появляться непосредственно слева.

(?<!:):[ ]

По частям

  • (?<!:) Отрицательный взгляд сзади, утверждение, что слева не двоеточие
  • :[ ] Соответствует двоеточию с пробелом (для ясности добавлены квадратные скобки)

Regex demo | Python демо

Например

import re
pattern = r"(?<!:): "
line = re.split(pattern, "A: ") # Result: ['A', '']
print(line)
line = re.split(pattern, ":: )5: ") # Result: [':: )5', '']
print(line)
line = re.split(pattern, "Delicious :): I want to eat this again") # Result: ['Delicious :)', 'I want to eat this again']
print(line)

Выход

['A', '']
[':: )5', '']
['Delicious :)', 'I want to eat this again']
0 голосов
/ 22 апреля 2020

Решение

Прежде всего, как вы показываете в своих примерах, вам нужно сопоставить символы, отличные от a-zA-Z0-9, поэтому мы должны просто использовать сопоставитель ., он будет соответствовать каждому символу.

Поэтому я думаю, что искомое выражение может быть таким:

(.*?):(?!.*:) (.*)

Вы можете использовать его так:

import re

pattern = r"(.*?):(?!.*:) (.*)"
matcher = re.compile(pattern)

txt1 = "A: "
txt2 = ":: )5: "
txt3 = "Delicious :): I want to eat this again"

result1 = matcher.search(txt1).groups() # ('A', '')
result2 = matcher.search(txt2).groups() # (':: )5', '')
result3 = matcher.search(txt3).groups() # ('Delicious :)', 'I want to eat this again')

Объяснение

Мы используем группы захвата (круглые скобки), чтобы получить разные части строки в разные группы, search затем находит эти группы и выводит их в кортеж.

Часть (?!.*:) называется " Negative Lookahead ", и мы используем его, чтобы убедиться, что мы начинаем захват с last :, который мы находим.

Edit

BTW, если, как вы упомянули, у вас есть много строк, каждая из которых содержит рецензию, вы можете использовать этот фрагмент, чтобы получить все рецензии, разделенные заголовком и телом сразу:

import re

pattern = r"(.*?):(?!.*:) (.*)\n?"
matcher = re.compile(pattern)

reviews = """ 
A: 
:: )5: 
Delicious :): I want to eat this again
"""

parsed_reviews = matcher.findall(reviews) # [('A', ''), (':: )5', ''), ('Delicious :)', 'I want to eat this again')]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...