Разделить строку в списке меток / значений с разными разделителями и содержимым значения

#python #regex

#python #регулярное выражение

Вопрос:

У меня есть строка со списком переменных / значений, например.

 string = " var1 = 20, var2  = hello    var3 =345.34  var4 = I have lost 
2,5 billions, var5 = Bill"
  

разделение кортежей может быть «,» или любым количеством пробелов, идентификация кортежей всегда «=»
проблема заключается в том, что некоторые значения содержат описательную строку с запятыми в качестве разделителя тысяч или, на худой конец, в качестве разделителя цифр.

Я попытался использовать последовательность re.sub и re.findall с регулярным выражением python, но я не могу правильно разделить кортеж var4, приведенный ниже кода :

 import re
string = " var1 = 20, var2  = hello    var3 =345.34  var4 = I lost 2,5 
billions, var5 = Bill"

t = re.sub('(=s )', '=', string)
t = re.sub('(s =)', '=', t)
result = re.findall("[A-Za-z0-9(,)=.] ", t)

print(result)
['var1=20,', 'var2=hello', 'var3=345.34', 'var4=I', 'lost', '2,5', 
'billions,', 'var5=Bill']
  

Мой ожидаемый результат

 ['var1=20', 'var2=hello', 'var3=345.34', 'var4=I lost 2,5 billions', 'var5=Bill']
  

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

1. Есть ли разрыв строки в строке? Или вы имели в виду написать """...""" ? Или это просто форматирование в вопросе?

2. Нет, в строке нет разрыва строки, это просто моя проблема с форматированием при отправке вопроса, извините

3. Хорошо, попробуйте result = re.split(r's (?=w =)', re.sub(r's*=s*', '=', s.strip()))

Ответ №1:

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

 re.split(r',?s (?=w =)', re.sub(r's*=s*', '=', s.strip()))
  

re.sub(r's*=s*', '=', s.strip()) Удалит пробелы вокруг = после удаления начальных / конечных пробелов в строке и r',?s (?=w =)' с re.split разделит строку на необязательную запятую, затем 1 или более пробелов, за которыми следуют символы 1 word, а затем = .

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

 import re
s = " var1 = 20, var2  = hello    var3 =345.34  var4 = I lost 2,5 billions, var5 = Bill"
result = re.split(r",?s (?=w =)", re.sub(r's*=s*', '=', s.strip()))
print(result)
# => ['var1=20', 'var2=hello', 'var3=345.34', 'var4=I lost 2,5 billions', 'var5=Bill']
  

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

1. Хорошо, проблема в том, что кортежи name =value могут быть разделены в строке запятыми или любым количеством пробелов, и запятые также могут быть внутри значения, например, var4 value -> «Я потерял 2,5 миллиарда» , но разделение от var4 и var5 тоже запятая …. миллиарды, var5 = Счет

2. @Alex Поделитесь строкой, которую у вас возникли проблемы с разделением при моем подходе, и укажите ожидаемый результат.

3. string = » var1 = 20, var2 = привет, var3 = 345,34, var4 = я потерял 2,5 миллиарда, var5 = Счет»

4. результат = [‘var1= 20’, ‘var2= привет’, ‘var3= 345.34’, ‘var4= я потерял 2,5 миллиарда’, ‘var5 = Счет’] как вы видите, var4 не содержит запятой в конце, потому что разделение между var4 и var5 — это запятая плюс пробел

5. @Alex обновлен, чтобы соответствовать этим новым требованиям.

Ответ №2:

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

 import re
string = " var1 = 20, var2  = hello    var3 =345.34  var4 = I have lost 2,5 billions, var5 = Bill"
vars = re.findall(r'var.*?(?=var|$)',string)
print(vars) # ['var1 = 20, ', 'var2  = hello    ', 'var3 =345.34  ', 'var4 = I have lost 2,5 billions, ', 'var5 = Bill']
  

Я использовал так называемый положительный прогноз (своего рода утверждение нулевой длины), поэтому findall ищет подстроки, за которыми следует var или конец str ( $ ). Как вы могли видеть, str s внутри vars все еще нуждаются в некоторой очистке. Сначала удалите конечные пробелы:

 vars = [i.strip(' ') for i in vars]
print(vars) # ['var1 = 20,', 'var2  = hello', 'var3 =345.34', 'var4 = I have lost 2,5 billions,', 'var5 = Bill']
  

Теперь ваш пример для меня неясен — я не знаю, хотите ли вы сохранить конечные , значения, как в var1 = 20, , или удалить их, как в var4=I lost 2,5 billions — поэтому я сохраняю , значения, поскольку они отмечают, что они могут быть удалены таким же образом, как показано для пробелов.
Наконец, чтобы удалить пробелы вокруг, = вы можете использовать re.sub следующий способ:

 vars = [re.sub(r' *= *','=',i,1) for i in vars]
print(vars) #['var1=20,', 'var2=hello', 'var3=345.34', 'var4=I have lost 2,5 billions,', 'var5=Bill']
  

Обратите внимание, что 1 in re.sub является преднамеренным, поэтому произойдет только 1 замена — так что пробелы будут удалены только вокруг первого = в каждом элементе vars . Вы можете отказаться от этого, 1 если вы уверены, что в каждом элементе не более 1 = .

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

1. Я хочу сохранить запятую, если она находится внутри значения переменной кортежа = value, например, в «2,5» значения var4, но не в том случае, если она находится в конце кортежа в качестве разделителя.

2. Нет, имя переменной изменяется в строке, единственной константой является разделение имени переменной и значения, и это <любое количество пробелов> = <любое количество пробелов> разделителем в моем примере являются пробелы или запятая, но пробелы и запятые также могут быть внутри значения