#python #regex
#python #регулярное выражение
Вопрос:
У меня есть несколько строк в формате
lorem ipsum, dolor sit - amet, consectetur : adipiscing elit. Praesent vitae orc
Я хочу, чтобы он был разделен в первом экземпляре каждого разделителя, чтобы вернуть
['lorem ipsum',
'dolor sit',
'amet, consectetur',
'adipiscing elit. Praesent vitae orc']
Прямо сейчас мой вывод
['lorem ipsum',
'dolor sit',
'amet',
'consectetur ',
'adipiscing elit. Praesent vitae orc']
Прямо сейчас я использую re.split(', | - |: ', txt)
, но он разделяет все экземпляры в строке. Есть предложения о том, как я могу добиться требуемого результата?
Редактировать:
Я понял, что мой вопрос неясен, поэтому, например, если строка
"abc: def: ijk, lmno: pqr - stu, wx"
вывод должен быть
["abc",
"def: ijk",
"lmno: pqr",
"stu, wxy"]
и не
["abc",
"def",
"ijk",
"lmno",
"pqr",
"stu",
"wxy"]
Комментарии:
1. Каков ваш желаемый результат?
2. @OrY желаемый результат находится в вопросе.
3. @MarkMeyer Запустите его регулярное выражение, это результат этого регулярного выражения. если это его желаемый результат, то у него нет проблем
4. @OrY виноват, добавил туда дополнительный пробел по ошибке, исправил это сейчас
5. @Thefourthbird да, это так
Ответ №1:
Если все разделители должны присутствовать хотя бы один раз, вместо использования разделения вы могли бы использовать 4 группы захвата с обратной ссылкой, соответствующей 1 из 3 вариантов, за исключением того, что уже сопоставлено.
^(.*?)(, | - |: )(.*?)(?!2)(, | - |: )(.*?)(?!2|4)(, | - |: )(.*)
Шаблон будет соответствовать
^
Начало строки(.*?)
Группа 1, совпадающая как можно меньше(, | - |: )
Группа 2, соответствует любому из перечисленных(.*?)
Группа 3, совпадение как можно меньше(?!2)
Отрицательный прогноз, утверждать, что то, что справа, не соответствует группе 2 (выберите один из 2 допустимых вариантов)(, | - |: )
Группа 4, соответствует любому из перечисленных(.*?)
Группа 5, совпадение как можно меньше(?!2|4)
Отрицательный прогноз, утверждать, что то, что справа, не соответствует группе 2 или группе 4 (выберите единственный допустимый вариант слева)(, | - |: )
Группа 6, соответствует любому из перечисленных(.*)
Группа 7, максимально сопоставьте любой символ
Демонстрация регулярных выражений
Например
import re
regex = r"^(.*?)(, | - |: )(.*?)(?!2)(, | - |: )(.*?)(?!2|4)(, | - |: )(.*)"
test_str = ("lorem ipsum, dolor sit - amet , consectetur : adipiscing elit. Praesent vitae orcnn"
"abc: def: ijk, lmno: pqr - stu, wxnn")
matches = re.search(regex, test_str, re.MULTILINE)
if matches:
print(matches.group(1))
print(matches.group(3))
print(matches.group(5))
print(matches.group(7))
Вывод
lorem ipsum
dolor sit
amet , consectetur
adipiscing elit. Praesent vitae orc
Комментарии:
1. Это было из-за плохого примера, который я выбрал, но скажем, что строка выглядит примерно так
abc: def: ijk, lmno: pqr - stu, wxy
, выходные данные должны быть разделены первыми экземплярами всех этих разделителей и должны возвращать["abc", "def: ijk" "lmno: pqr", "stu, wxy"]
Я отредактирую вопрос, чтобы отразить то же самое2. @Eagle Итак, вы сначала хотите разделить на
,
Затем на ` — `, а затем на:
?3. Больше похоже на разделение только в трех местах #1, где
,
появляется впервые # 2, где:
появляется впервые # 3, где ` — ` появляется впервые4. @Eagle Я изменил ответ, используя группы захвата.
Ответ №2:
Просто пища для размышлений, не уверен, что это ценный ответ, но, возможно, если вы сможете использовать модуль regex
вместо re
, чтобы использовать возможность отрицательного просмотра сзади с нефиксированной шириной. Например:
s*([,:-])(?<!1.*1)s*
В Python:
import regex as re
string1 = "abc: def: ijk, lmno: pqr - stu, wx"
lst1 = re.sub(r's*([,:-])(?<!1.*1)s*', '|' , string1).split('|')
print(lst1)
Результат:
['abc', 'def: ijk', 'lmno: pqr', 'stu, wx']
Комментарии:
1. Большое спасибо, это сработало, но как я мог разделить его на ` — ` вместо
-
и на:
вместо:
? Например, с пробелами до и после-
и пробелом после:
2. Не уверен, что я вас достаточно хорошо понимаю. Может быть, использовать вместо *?
Ответ №3:
Вы могли бы использовать небольшой класс, который подсчитывает замены:
import re
text = "lorem ipsum, dolor sit - amet, consectetur : adipiscing elit. Praesent vitae orc"
# text = "abc: def: ijk, lmno: pqr - stu, wx"
rx = re.compile(r'[-,:]')
class Replacer:
def __init__(self, *args, **kwargs):
for key in args:
setattr(self, key, 0)
self.needle = kwargs.get("needle")
def __call__(self, match):
key = match.group(0)
setattr(self, key, getattr(self, key, 0) 1)
cnt = getattr(self, key, 0)
return self.needle if cnt == 1 else key
rpl = Replacer("-", ",", ":", needle="#@#")
result = [item.strip() for item in re.split("#@#", rx.sub(rpl, text))]
print(result)
Что дает
['lorem ipsum', 'dolor sit', 'amet, consectetur', 'adipiscing elit. Praesent vitae orc']