2016-01-26 4 views
2

У меня есть строка, как такой testing_7_3_4_testingRegex для извлечения трех символов из строки питона

я хочу, чтобы заменить testing_7_3_4_testing с testing_7.3.4_testing, я попытался с помощью str.replace(/\d_\d/, ".") и им получить некоторые действительно странные результаты. Эксперты Regex, пожалуйста, помогите!

+1

Возможно, результаты странные, потому что вы используете JS-код в Python? –

+0

Я также пробовал этот re.findall (r '[\ d_ \ d]', str), но он соответствует только первому набору «7_3», а не «7_3_4» – Rafthecalf

ответ

4

Попробуйте это:

import re 

my_strs = [ 
    'testing_7_3_4_testing', 
    'testing_7_3_testing', 
    'testing_7_3_4_5', 
    'testing_71_312_4123_testing', 
] 

pattern = r""" 
    (\d+)  #Match a digit, one or more times, captured in group 1, followed by... 
    _   #an underscore, followed by... 
    (?=\d+) #a digit, one or more times, but do not include as part of the match 
""" 

for my_str in my_strs: 
    new_str = re.sub(pattern, r'\1.', my_str, flags=re.X) 
    print(new_str) 

--output:-- 
testing_7.3.4_testing 
testing_7.3_testing 
testing_7.3.4.5 
testing_71.312.4123_testing 

Узор (?=\d+) говорит, чтобы соответствовать цифре, один или несколько раз, но на самом деле не включать совпадающие цифры как часть матч.

+1

это гораздо более умное решение – tinySandy

+0

Не могли бы вы объяснить шаблон, пожалуйста? – Rafthecalf

+0

@RafaelGutierrez, я добавил несколько комментариев к шаблону. Трудная часть - '(? = ...)', которая называется 'lookahead'. Он соответствует чему-то еще впереди в строке, но не включает ту часть матча в фактическом совпадении. – 7stud

2

Сохранить каждая цифра в его собственной saving group, ссылки на группы в вашей строке замены:

>>> import re 
>>> s = "testing_7_3_4_testing" 
>>> re.sub(r"(\d)_(\d)_(\d)", r"\1.\2.\3", s) 
'testing_7.3.4_testing' 

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

>>> def replacement(m): 
...  x, y, z = m.groups() 
...  return x + y.replace("_", ".") + z 
... 
>>> re.sub(r"(.*?_)([0-9_]+)(_.*?)", replacement, s) 
'testing_7.3.4_testing' 

не-регулярное выражение подход предполагает Расщепление _, нарезка и соединение:

>>> l = s.split("_") 
>>> l[0] + "_" + ".".join(l[1:-1]) + "_" + l[-1] 
'testing_7.3.4_testing' 
+0

Что делать, если есть более трех чисел? –

+0

@ WiktorStribiżew Этот конкретный шаблон не масштабируется много, хорошая точка, но цифры выглядят как часть версии, давайте посмотрим, достаточно ли это для OP. Благодарю. – alecxe

+0

как насчет переменного числа выделенных подчеркнутых чисел? i.e testing_7_3_4_testing или testing_3_4_testing и т. д. – Rafthecalf

Смежные вопросы