строка соответствия регулярного выражения Python, если существует или нет - PullRequest
1 голос
/ 17 февраля 2011

У меня небольшая проблема с регулярным выражением.

Вот пример текста для разбора:

output = """
country : USA
zzzzzzz
continent : Americ
eeeeeee
------
country : China
zzzzzzz
continent : Asia
planet : Earth
-------
country : Izbud
zzzzzzz
continent : Gladiora
zzzzzzz
zzzzzzz
planet : Mars
"""

Я хочу разобрать это и вернуть страну, континент и, в конечном итоге, планету.

Итак, я сделал регулярное выражение:

results = re.findall(
    r"""(?mx)
        ^country\s:\s*(.+)\s
        (?:^.+\s)*?
        ^continent\s:\s*(.+)\s
        (?:^.+\s)*?
        (?:^planet\s:\s*(.+)\s)*?
""",output)

но возвращаемое значение:

[('USA', 'Americ', ''), ('China', 'Asia', ''), ('Izbud', 'Gladiora', '')]

И я не знаю, где мое регулярное выражение не так?

Если у кого-то есть идея, спасибо.

Ответы [ 6 ]

1 голос
/ 17 февраля 2011

Я нашел шаблон, который, кажется, работает:

r"""(?mx)
    ^country\s:\s*(.+)\s
    (?:^.+\s)*?
    ^continent\s:\s*(.+)\s
    (?:^.+\s)*?
    (?:^(?:planet\s:\s*(.+)\s|-+\s|\Z))
"""

По сути, я изменил последнюю часть так, чтобы она соответствовала одному из следующих элементов: планета, группа элементов,или конец строки.Это некрасиво, но это был единственный способ, который я мог найти, чтобы убедиться, что он получил планету.Одна проблема с моим решением состоит в том, что в конце строки должна быть пустая строка (как в вашем примере), иначе не будет последнего совпадения.

Кстати, частичное решениеисправить последнюю строку шаблона OP, чтобы он просто имел?в конце, а не * ?.Однако он будет соответствовать только информации о планете, которая является строкой, следующей за информацией о континенте.Причина, по которой он ничего не получил раньше, в том, что *?ленивыйЭто позволит избежать совпадения, если это возможно.

1 голос
/ 17 февраля 2011

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

while true:
    line = readline()
    if line == "----------":
        # Do cleanup stuff
        continue
    elif 'country' in line.split():
        country = line.split()[2]
    elif 'continent' in line.split():
        continent = line.split()[2]
    # etc...
    # update your list or dict or w/e
    line = readline()
0 голосов
/ 17 февраля 2011
import re

pat = re.compile('country : (.+)\n.+\ncontinent : (.+)(?:\n.*)*?(?:\nplanet : (.+)|\n-+|\n?\Z)')

output1 = """
country : USA
zzzzzzz
continent : Americ
eeeeeee
------
country : China
zziiiiiiiiiiiizz
continent : Asia
planet : Earth
-------
country : Izbud
zzuuuuuuuuuuuuz
continent : Gladiora
zzzzzzz
uyututuug
planet : Mars """

output2 = """
country : USA
zzzzzzz
continent : Americ
eeeeeee
------
country : Izbud
zzuuuuuuuuuuuuz
continent : Gladiora
zzzzzzz
uyututuug
"""

output3 = """
country : USA
zzzzzzz
continent : Americ
eeeeeee
-------
country : Izbud
zzuuuuuuuuuuuuz
continent : Gladiora
zzzzzzz
uyututuug"""

output4 = """
country : USA
zzzzzzz
continent : Americ
eeeeeee
-------
country : Izbud
zzuuuuuuuuuuuuz
continent : Gladiora
"""

output5 = """
country : USA
zzzzzzz
continent : Americ
eeeeeee
-------
country : Izbud
zzuuuuuuuuuuuuz
continent : Gladiora"""

for ch in (output1,output2,output3,output4,output5):
    print ch
    print
    print repr(ch)
    print
    print '\n'.join(repr(u) for u in pat.findall(ch))
    print '======================================================================'

Результат:

country : USA
zzzzzzz
continent : Americ
eeeeeee
------
country : China
zziiiiiiiiiiiizz
continent : Asia
planet : Earth
-------
country : Izbud
zzuuuuuuuuuuuuz
continent : Gladiora
zzzzzzz
uyututuug
planet : Mars 

'\ncountry : USA\nzzzzzzz\ncontinent : Americ\neeeeeee\n------\ncountry : China\nzziiiiiiiiiiiizz\ncontinent : Asia\nplanet : Earth\n-------\ncountry : Izbud\nzzuuuuuuuuuuuuz\ncontinent : Gladiora\nzzzzzzz\nuyututuug\nplanet : Mars '

('USA', 'Americ', '')
('China', 'Asia', 'Earth')
('Izbud', 'Gladiora', 'Mars ')
======================================================================

country : USA
zzzzzzz
continent : Americ
eeeeeee
------
country : Izbud
zzuuuuuuuuuuuuz
continent : Gladiora
zzzzzzz
uyututuug


'\ncountry : USA\nzzzzzzz\ncontinent : Americ\neeeeeee\n------\ncountry : Izbud\nzzuuuuuuuuuuuuz\ncontinent : Gladiora\nzzzzzzz\nuyututuug\n'

('USA', 'Americ', '')
('Izbud', 'Gladiora', '')
======================================================================

country : USA
zzzzzzz
continent : Americ
eeeeeee
-------
country : Izbud
zzuuuuuuuuuuuuz
continent : Gladiora
zzzzzzz
uyututuug

'\ncountry : USA\nzzzzzzz\ncontinent : Americ\neeeeeee\n-------\ncountry : Izbud\nzzuuuuuuuuuuuuz\ncontinent : Gladiora\nzzzzzzz\nuyututuug'

('USA', 'Americ', '')
('Izbud', 'Gladiora', '')
======================================================================

country : USA
zzzzzzz
continent : Americ
eeeeeee
-------
country : Izbud
zzuuuuuuuuuuuuz
continent : Gladiora


'\ncountry : USA\nzzzzzzz\ncontinent : Americ\neeeeeee\n-------\ncountry : Izbud\nzzuuuuuuuuuuuuz\ncontinent : Gladiora\n'

('USA', 'Americ', '')
('Izbud', 'Gladiora', '')
======================================================================

country : USA
zzzzzzz
continent : Americ
eeeeeee
-------
country : Izbud
zzuuuuuuuuuuuuz
continent : Gladiora

'\ncountry : USA\nzzzzzzz\ncontinent : Americ\neeeeeee\n-------\ncountry : Izbud\nzzuuuuuuuuuuuuz\ncontinent : Gladiora'

('USA', 'Americ', '')
('Izbud', 'Gladiora', '')
======================================================================
0 голосов
/ 17 февраля 2011

Я полностью согласен со всеми, кто сказал, что вы не должны делать это с регулярным выражением.Тем не менее, вы можете заставить его работать, если вы используете отрицательный прогноз, прежде чем использовать каждую «ненужную» строку.Например:

print re.findall(r"""(?mx)
    ^country\s:\s*(.+)\s
    (?:^.+\s)*?
    ^continent\s:\s*(.+)\s
    (?:(?:(?!(?:planet|country|continent)\s:)^.+\s)*
       (?:^planet\s:\s*(.+)\s))?
""",output)
0 голосов
/ 17 февраля 2011
# seen this '\n' can break string into LIST of strings 

n_line = output.split('\n')

tempn_line = n_line[:]

# loop through the new List (without '\n')

for n_text in tempn_line:
    if ':' not in n_text:
        #print n_text
        n_line.remove(n_text)


for l_text in n_line:
    n_split = l_text.split(':')
    #print n_split
    if 'country' in n_split[0]:
        print n_split[1]
    elif 'continent' in n_split[0]:
        print n_split[1]
    elif 'planet' in n_split[0]:
        print n_split[1]
0 голосов
/ 17 февраля 2011

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

"""(?mx)
        ^country\s:\s*(.+)\s
        (?:^.+\s)*?
        ^continent\s:\s*(.+)\s
        (?:^.+\s)*?
        ^planet\s:\s*(.+)\s.*
"""
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...