Не повезло найти шаблон регулярного выражения Python - PullRequest
2 голосов
/ 05 ноября 2019

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

REF*0F*452574437~
REF*1L*627783972~
REF*23*526344060~
REF*6O*1024817112~
DTP*336*D8*20140623~
DTP*473*D8*20191001~
DTP*474*D8*20191031~
DTP*473*D8*20191101~

Я хочу извлечь строки, начинающиеся с "REF * 23* "и заканчивая" ~ "

txtfile = open(i + fileName, "r")
for line in txtfile:
    line = line.rstrip()
    p = re.findall(r'^REF*23*.+~', line)
    print(p)

Но это мне ничего не дает. Как бы мне не хотелось углубляться в регулярные выражения с python, мне нужно быстрое решение этого вопроса. То, что я в конечном итоге хочу, это просто цифры между последним "*" и "~" Спасибо

Ответы [ 3 ]

3 голосов
/ 05 ноября 2019

В действительности вам не нужно регулярное выражение, если единственной задачей является для извлечения строк, которые начинаются с "REF * 23 *" и заканчиваются на "~" :

results = []
with open(i + fileName, "r") as txtfile:
    for line in txtfile:
        line = line.rstrip()
        if line.startswith('REF*23*') and line.endswith('~'):
            results.append(line)

print(results)

Если вам нужно получить куски цифр:

results = []
with open(i + fileName, "r") as txtfile:
    for line in txtfile:
        line = line.rstrip()
        if line.startswith('REF*23*') and line.endswith('~'):
            results.append(line[7:-1]) # Just grab the slice

См. демонстрация подхода без регулярных выражений .

ПРИМЕЧАНИЯ

  • В регулярном выражении * должен быть экранирован, чтобы соответствовать буквальной звездочке
  • Вы читаете построчно, re.findall(r'^REF*23*.+~', line) не имеет смысла, поскольку метод re.findallиспользуется для получения нескольких совпадений, в то время как вы ожидаете одно
  • Ваше регулярное выражение не привязано справа, вам нужно $ или \Z, чтобы соответствовать ~ в конце строки. Так что, если вы хотите использовать регулярное выражение, оно будет выглядеть следующим образом:

    m = re.search(r'^REF\*23\*(.*)~$', line): if m: results.append(m.group(1)) # To grab just the contents between delimiters # or results.append(line) # To get the whole line

    См. Эту демонстрацию Python

  • В вашем случае вы ищете строки, которые начинаются и заканчиваются фиксированным текстом, поэтому нет необходимости использовать регулярное выражение.

Редактировать как ответ на комментарий

Другой текстовый файл очень длинный, без разрывов, почти без пробелов. Мне нужно найти, где раздел начинается с REF*0F* и заканчивается ~, с нужным номером между ними.

Вы можете читать файл построчно и захватывать все вхождения 1+ цифр между REF*0F* и ~:

results = []
with open(fileName, "r") as txtfile:
    for line in txtfile:
        res = re.findall(r'REF\*0F\*(\d+)~', line)
        if len(res):
            results.extend(res)

print(results)
1 голос
/ 05 ноября 2019

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

raw = """
REF*0F*452574437~
REF*1L*627783972~
REF*23*526344060~
REF*6O*1024817112~
DTP*336*D8*20140623~
DTP*473*D8*20191001~
DTP*474*D8*20191031~
DTP*473*D8*20191101~
"""

result = [digits[:-1]
          for line in raw.split("\n") if line.startswith("REF*23*") and line.endswith("~")
          for splitted in [line.split("*")]
          for digits in [splitted[-1]]]
print(result)

Это дает

['526344060']
1 голос
/ 05 ноября 2019

* - это специальный символ в регулярном выражении, поэтому вы должны избегать его, как указывает @The Fourth Bird. Вы используете необработанную строку, что означает, что вам не нужно экранировать символы при разборе строки на языке Python, но вы все равно должны экранировать ее для механизма регулярных выражений.

r'^REF\*23\*.+~'

или

'^REF\\*23\\*.+~'
# '\\*' -> '\*' by Python string
# '\*' matches '*' literally by regex engine

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

Дополнительные изменения

Возможно, вы также захотите разбрасывать парень .+, чтобы соответствовать группе, если вы хотите соответствовать ей. Также измените значение findall на match, если вы не ожидаете нескольких совпадений на строку.

results = []
with open(i + fileName, "r") as txtfile:
    line = line.rstrip()
    p = re.match(r'^REF\*23\*(.+)~', line)
    if p:
        results.append(int(p.group(1)))

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

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