Регулярное выражение для совпадения с последним и первым номером в выходном файле - PullRequest
1 голос
/ 08 апреля 2020

У меня есть два набора выходных файлов. Я хочу захватить первый номер после виртуального и последний номер перед виртуальным. Я нашел регулярное выражение для первого вывода:

rx_orb = re.compile(
    r'''(?P<HOMO>-?\d.\d{3}$)((.*\n){,2})\s*(.*?Virtual.*$\s*?)(?P<LUMO>-?\d.\d{3})''',
    re.MULTILINE)

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

LUMO:  0.028
HOMO:  -0.448

Как найти регулярное выражение, которое работает для обоих выходных файлов? Я выделил цифры, которые мне нужны ниже:

-0.824  -0.732  -0.715  -0.694  -0.627  -0.619  -0.607  -0.571
 -0.544  -0.518  -0.504  -0.495  -0.495  -0.477  -0.453  -0.448
 -0.422  -0.379  -0.370  -0.325  -0.305  **-0.263**
 -- Virtual --
  **0.028**   0.072   0.109   0.163   0.188   0.191   0.199   0.215
  0.239   0.266   0.277   0.278   0.296   0.322   0.348   0.363
  0.399   0.409   0.431   0.439   0.448   0.539   0.557   0.593
 9 Au    9 Ag   10 Au   10 Ag   11 Ag   11 Au   12 Ag   13 Ag                 
-0.497  -0.482  -0.478  -0.447  -0.415  -0.410  -0.407  -0.362
12 Au   13 Au   14 Au   15 Au   14 Ag   15 Ag   16 Ag   17 Ag                 
-0.313  **-0.284**
16 Au   17 Au                                                                 
-- Virtual --                   
 **0.031**   0.062   0.111   0.177   0.186   0.197   0.206   0.253
18 Ag   19 Ag   18 Au   20 Ag   19 Au   20 Au   21 Au   21 Ag                 
 0.256   0.261   0.267   0.292   0.295   0.327   0.366   0.391

1 Ответ

1 голос
/ 08 апреля 2020

Как вы используете это регулярное выражение в своем коде? Может быть, вы забыли установить флаг re.MULTILINE при работе со строками?

Этот пример работает должным образом:

import re

TEXT1 = """-0.422  -0.379  -0.370  -0.325  -0.305  -0.263
-- Virtual --
0.028   0.072   0.109   0.163   0.188   0.191   0.199   0.215
0.239   0.266   0.277   0.278   0.296   0.322   0.348   0.363
"""

TEXT2 = """9 Au    9 Ag   10 Au   10 Ag   11 Ag   11 Au   12 Ag   13 Ag
-0.497  -0.482  -0.478  -0.447  -0.415  -0.410  -0.407  -0.362
12 Au   13 Au   14 Au   15 Au   14 Ag   15 Ag   16 Ag   17 Ag
-0.313  -0.284
16 Au   17 Au
-- Virtual --
 0.031   0.062   0.111   0.177   0.186   0.197   0.206   0.253
18 Ag   19 Ag   18 Au   20 Ag   19 Au   20 Au   21 Au   21 Ag
 0.256   0.261   0.267   0.292   0.295   0.327   0.366   0.391
"""

if __name__ == '__main__':
    my_re = r'(?P<HOMO>-?\d.\d{3}$)((.*\n){,2})\s*(.*?Virtual.*$\s*?)(?P<LUMO>-?\d.\d{3})'
    m = re.search(my_re, TEXT1, re.MULTILINE)
    print(m.groupdict())
    m = re.search(my_re, TEXT2, re.MULTILINE)
    print(m.groupdict())

Вывод:

{'HOMO': '-0.263', 'LUMO': '0.028'}
{'HOMO': '-0.284', 'LUMO': '0.031'}

Обновление:

Однако вы можете столкнуться с проблемами при использовании Python 2 и чтении файлов с переносом строк в стиле DOS (^M). В этом случае вам необходимо учитывать, что в переводе строки будет добавлен дополнительный символ возврата каретки \r. Вы должны использовать \r\n, чтобы найти разрывы строк и рассмотреть возможность использования опции re.DOTALL , которая позволяет сопоставлять символы новой строки с символом точки (.).

Грубое решение может удалить все \r символов после чтения из файла, например:

    with open('file-windows-linebreaks.txt') as f:
        data = f.read()
        data = data.replace('\r\n', '\n')
        # Use regex on data

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

Кстати, это поведение было исправлено в Python 3 open . Согласно документации, open имеет универсальный параметр newline:

newline controls how universal newlines works (it only applies to text mode).
It can be None, '', '\n', '\r', and '\r\n'.

Таким образом, ваше регулярное выражение будет работать в Python 3 без каких-либо дополнительных действий.

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