Как пользоваться '?'извлечь необязательную подстроку между двумя соответствующими шаблонами в Python? - PullRequest
0 голосов
/ 28 января 2019

Я был отвечая на этот вопрос n.Рассмотрим эту строку

str1 = '{"show permission allowed to 16": "show permission to 16\\nSchool permissions from group 17:student to group 16:teacher:\\n\\tAllow ALL-00\\nSchool permissions from group 18:library to group 16(Temp):teacher:\\n\\tNo Allow ALL-00\\nSchool permissions from group 20:Gym to group 16:teacher:\\n\\tCheck ALL-00\\nRTYAHY: FALSE\\nRTYAHY: FALSE\\n\\n#"}'

и предположим, что я хочу извлечь число после каждой подстроки from group и подстроки после \\t с наименьшей соответствующей строкой.

Я сделал это сследующее регулярное выражение

import re
res = re.findall(r'from group (\d+).*?\\t(.*? ALL-..)', str1)

вывод:

[('17', 'Allow ALL-00'), ('18', 'No Allow ALL-00'), ('20', 'Check ALL-00')]

Теперь между каждой извлекаемой подстрокой (число и подстрока после \t) может быть необязательная подстрока, чьязначение Temp Я хочу извлечь (если есть).Например, между 18 и No Allow ALL-00 есть подстрока Temp, которую я хотел бы извлечь.

Я попытался использовать ? следующим образом:

res = re.findall(r'from group (\d+).*?(Temp)?.*?\\t(.*? ALL-..)', str1)

, но соответствующийВторой элемент результирующих кортежей всегда пуст:

[('17', '', 'Allow ALL-00'), ('18', '', 'No Allow ALL-00'), ('20', '', 'Check ALL-00')]

, пока я ожидал что-то вроде:

[('17', '', 'Allow ALL-00'), ('18', 'Temp', 'No Allow ALL-00'), ('20', '', 'Check ALL-00')]

Как извлечь подстроки в этом случае?В чем заключается ошибка, которую я делаю?

Еще один вопрос: предположим, я хочу, чтобы в моем результирующем списке не было этого элемента (содержащего Temp): нужно ли просто использовать [^] и затем соответствующий шаблон сопоставления

1 Ответ

0 голосов
/ 28 января 2019

Причина, по которой он не захватывает Temp, заключается в том, что вы сделали его необязательным, из-за которого .*? потребляет его, а Temp не попадает в дополнительную группу.

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

from group (\d+)(?:(?!Temp).)*?(Temp)?(?:(?!Temp).)*?\\t(.*? ALL-..)
                   ^^^^^^^^^ This rejects Temp getting captured except any other character

Объяснение регулярного выражения:

  • from group - буквальное соответствие этого текста
  • (?:(?!Temp).)*? - ?: означает, что это группа без захвата, которая по умолчанию является группой захвата, и это означает, что захват всего, кроме остановки, когда вы видите Temp строка и * означает захват ноля или более символов.Таким образом, это захватывает любую строку, которая не содержит Temp и ? означает как можно меньше
  • (Temp)? - Опционально захватывает Temp, если присутствует
  • (?:(?!Temp).)*? - Опятьзахватить любой символ ноль или более раз, кроме Temp, как указано выше
  • \\t - захватить это буквально
  • (.*? ALL-..) - захват любого символа как можно меньше, за которым следует пробел с последующим пробеломлитерал ALL-, за которым следуют любые два символа

Надеюсь, это прояснит регулярное выражение.Сообщите мне, если у вас возникнут дополнительные вопросы.

Демо

Образцы кодов Python,

import re

s = '{"show permission allowed to 16": "show permission to 16\\nSchool permissions from group 17:student to group 16:teacher:\\n\\tAllow ALL-00\\nSchool permissions from group 18:library to group 16(Temp):teacher:\\n\\tNo Allow ALL-00\\nSchool permissions from group 20:Gym to group 16:teacher:\\n\\tCheck ALL-00\\nRTYAHY: FALSE\\nRTYAHY: FALSE\\n\\n#"}'

arr = re.findall(r'from group (\d+)(?:(?!Temp).)*?(Temp)?(?:(?!Temp).)*?\\t(.*? ALL-..)',s)
print(arr)

Печать,

[('17', '', 'Allow ALL-00'), ('18', 'Temp', 'No Allow ALL-00'), ('20', '', 'Check ALL-00')]

Редактировать: Для перечисления только кортежей, которые не содержат Temp

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

from group (\d+)(?:(?!Temp).)*\\t(.*? ALL-..)

Демо

Пример кода Python,

import re

str1 = '{"show permission allowed to 16": "show permission to 16\\nSchool permissions from group 17:student to group 16:teacher:\\n\\tAllow ALL-00\\nSchool permissions from group 18:library to group 16(Temp):teacher:\\n\\tNo Allow ALL-00\\nSchool permissions from group 20:Gym to group 16:teacher:\\n\\tCheck ALL-00\\nRTYAHY: FALSE\\nRTYAHY: FALSE\\n\\n#"}'

arr = re.findall(r'from group (\d+)(?:(?!Temp).)*\\t(.*? ALL-..)',str1)
print(arr)

Печать,

[('17', 'Allow ALL-00'), ('20', 'Check ALL-00')]

Который не содержит кортеж, имеющий Temp

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