Как учесть возможный пробел между подобранными словами? - PullRequest
1 голос
/ 29 января 2020

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

a description without tags
[one] [two] hello
[single] world

Это должно вернуть меня соответственно:

  • a description without tags
  • one, two, hello
  • single, word

Идея состоит в том, чтобы иметь в качестве входных данных: необязательно a [tag] (или более, разделенных пробелом) и описание - в идеале сгруппированные в список тегов (возможно, пустых) и строку описания.

Я думаю, что я сопоставил эти случаи с (\[(\S+)\])*.+. Однако я не уверен, правильно ли пропущен пробел между тегами.

В любом случае реальность такова, что мои пользователи-подростки, набирающие текст для подростков, получат такие записи, как

[glued1][glued2] wazaa
[glued10][glued20]glued decription
[glued]wazii

и подобные.

Я хотел бы построить регулярное выражение, которое скажет "от начала строки, взять то, что находится между [ и ], столько раз насколько возможно (возможно, ноль) и верните мне эти совпадения, и то, что следует за последними ] минус возможные промежутки между ними ".

Не слишком ли это сложно для регулярного выражения? Альтернатива состоит в том, чтобы анализировать строку символ за символом - что я смогу сделать, но это будет менее изящно.

Или - альтернативно - как далеко я могу go с регулярным выражением, и отказаться от в других случаях (они увидят, что что-то не так, если то, что они вводят, все равно не анализируется правильно)

Ответы [ 5 ]

0 голосов
/ 29 января 2020

Это, кажется, работает нормально, насколько я понимаю ваши потребности:

(^[\[]+\]|[\w\s]+)+

https://regex101.com/r/0cA95I/1

0 голосов
/ 29 января 2020

Я думаю, у вас это почти есть. Это даст вам то, что вы хотите?

^(\[\S+\]\s*)*\s*(.+)

^ обозначает начало строки. \s обозначает пробел. Итак, это говорит: в начале строки ищите, что в скобках 0 или более раз. Затем найдите 0 или более пробелов, затем сопоставьте то, что будет после. Единственная проблема с этим состоит в том, что он захватывает пробелы, которые могут или не могут быть между тегами. Чтобы решить эту проблему, возможно, вам понадобится шаг постобработки для удаления пробелов.

0 голосов
/ 29 января 2020

Для простоты вы можете просто сопоставить все содержимое в квадратных скобках с помощью простого регулярного выражения r"\[(.*?)\]". Мы проверим это на приведенных примерах:

test_str = ['[glued1][glued2] wazaa','[glued10][glued20]glued decription','[glued]wazii','a description without tags','[one] [two] hello','[single] world']

Шаг за шагом:

import re
regex = r"\[(.*?)\]"
for s in test_str:
    print(f"{s} -> {re.findall(regex, s)}")
        print(re.findall(regex, s))

Что приводит к:

'[glued1][glued2] wazaa' -> ['glued1', 'glued2']
'[glued10][glued20]glued decription' -> ['glued10', 'glued20']
'[glued]wazii' -> ['glued']
'a description without tags' -> []
'[one] [two] hello' -> ['one', 'two']
'[single] world' -> ['single']

ПРОБЛЕМА! Это не работает, если вы используете квадратные скобки где-то внутри описания.

0 голосов
/ 29 января 2020

Если ваша строка не будет содержать никаких скобок, кроме тегов ', вы можете попробовать использовать регулярное выражение, которое соответствует всему, кроме самих скобок (и пробелов):

[^ \[\]]* 

https://regex101.com/r/pUXAVC/1

Редактировать: Это решение разделит токены описаний на отдельные группы. Если вы хотите, чтобы они были сгруппированы вместе, вы можете просто удалить символ пробела из регулярного выражения [^\[\]]* и обрезать дополнительные пробелы, которые вы получаете в своих группах.

0 голосов
/ 29 января 2020

Разве это не слишком сложно для регулярных выражений?

Да, по крайней мере для Python, вам придется сделать это в два этапа:

  • либо сопоставляет все теги по отдельности (используя re.finditer), затем берет все, что осталось после последнего соответствия (это будет вашим описанием)
  • , либо сопоставляет все теги как одну группу и отдельно, затем сопоставьте ваши теги в первой группе

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

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