Как использовать несколько токенов с использованием выражения регулярных выражений

#python #regex

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

Вопрос:

Для извлечения первых трех букв «abc» и трех наборов трехзначных чисел в 000_111_222 я использую следующее выражение:

 text = 'abc_000_111_222'
print re.findall('^[a-z]{3}_[0-9]{3}_[0-9]{3}_[0-9]{3}', text)
 

Но выражение возвращает пустой список, когда вместо подчеркивания вместо этого используются минусы или точки: abc.000.111.222 или abc-000-111-222 или любая их комбинация, например: abc_000.111-222

Конечно, я мог бы использовать простой метод замены для унификации текстовой переменной text=text.replace('-','_').replace('.','_')

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

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

1. Заменить символ подчеркивания на что-то, что соответствует любому из трех символов?

2. еще несколько примеров строк прольют больше света на то, чего вы пытаетесь достичь

3. print re.findall(r'^[a-z]{3}(?:[_.-]d{3}){3}$', text) должно работать

4. @anubhava, шаблон можно повторить только дважды, так как строка не заканчивается на _

5. Нет, _ перед первым номером также есть.

Ответ №1:

Вы можете использовать классы символов регулярных выражений с [ ] . В вашем случае это может быть [_.-] (обратите внимание на дефис в конце, если его нет в конце, он будет рассматриваться как диапазон, подобный [a-z] ).

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

 print re.findall('^[a-z]{3}[_.-][0-9]{3}[_.-][0-9]{3}[_.-][0-9]{3}', text)
 

введите описание изображения здесь

Кстати, вы можете сократить свое регулярное выражение, чтобы получить что-то вроде этого:

 print re.findall('^[a-z]{3}[_.-](d{3}[_.-]){2}d{3}', text)
 

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

 ^[a-z]{3}([_.-])[0-9]{3}1[0-9]{3}1[0-9]{3}
 

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

1. Потрясающий ответ! Спасибо!

2. @буквенно-цифровой рад помочь

Ответ №2:

Почему бы не отказаться regexes вообще и использовать более понятное и простое решение?

 $ cat /tmp/tmp.py
SEP = '_.,;-= '

def split_str(text):
    for s in list(SEP):
        res = text.split(s)
        if len(res) > 1:
            return text.split(s)

print(split_str('abc_000_111_222'))
print(split_str('abc;000;111;222'))
print(split_str('abc.000.111.222'))
print(split_str('abc-000-111-222'))
 

Что дает:

 $ python3 /tmp/tmp.py
['abc', '000', '111', '222']
['abc', '000', '111', '222']
['abc', '000', '111', '222']
['abc', '000', '111', '222']

$