Выделить определенную часть строки с регулярным выражением в Python - PullRequest
1 голос
/ 11 декабря 2019

У меня есть различные строки вида _AHDHDUHD[Tsfs (SGYA)]AHUDSHDI_, и я хочу вырезать часть (SGYA) (всегда заглавные буквы в круглых скобках) и возможные пробелы непосредственно перед или после нее. Таким образом, результат должен быть _AHDHDUHD[Tsfs]AHUDSHDI_.

У меня была идея сопоставить содержимое квадратных скобок с ([A-Z_])(\[.+\])([A-Z_]), а затем выполнить разбиение и заново вставить его, используя модуль re (хотя яне уверен, какая функция re подходит для этого).

Однако это выглядит не элегантно. Есть ли regex, который будет делать то, что я хочу напрямую, без промежуточных шагов?

Ответы [ 3 ]

1 голос
/ 11 декабря 2019

Вы можете использовать

re.sub(r'(\[[^][]*?)\s*\([A-Z]*\)\s*([^][]*])', r'\1\2', text)

См. Демоверсию regex

Подробности

  • (\[[^][]*?)- Группа 1: [, а затем любые 0+ символов, кроме [ и ], как можно меньше
  • \s* - 0+ пробелов
  • \( -a ( char
  • [A-Z]* - 0+ прописных букв ASCII
  • \) - ) char
  • \s* - 0+ пробелов
  • ([^][]*]) - Группа 2: любые 0+ символов, кроме ] и [ (столько, сколько возможно), а затем ]

Демонстрация Python:

import re
rx = r"(\[[^][]*?)\s*\([A-Z]*\)\s*([^][]*])"
s = "_AHDHDUHD[Tsfs (SGYA)]AHUDSHDI"
print( re.sub(rx, r'\1\2', s) )
# => _AHDHDUHD[Tsfs]AHUDSHDI

Другая идея: удалить только все \s*\([A-Z]+\)\s* совпадений, если они найдены внутри [...] подстрок:

import re
s = "_AHDHDUHD[Tsfs (SGYA)]AHUDSHDI"
print( re.sub(r"\[[^][]+]", lambda x: re.sub(r'\s*\([A-Z]+\)\s*', "", x.group()), s) )
# => _AHDHDUHD[Tsfs]AHUDSHDI

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

Здесь шаблон \[[^][]+] найдет все фрагменты [, затем 1+ символов, кроме квадратных скобок, а затем ], а затем любые вхождения 0+ пробелов, (, 1+ заглавные буквы ASCII, ) и 0+ пробелы будут удалены только внутри найденных совпаденийс рисунком \[[^][]+].

0 голосов
/ 11 декабря 2019

Вы ищете функцию re.sub

import re
s = "AHDHDUHD[Tsfs (SGYA)]AHUDSHDI" 
s_re = re.sub("(.*?)(\s*\(.*?\)\s*)(.*?)", '', s)
print (s_re)

Она напечатает:

AHDHDUHD[Tsfs]AHUDSHDI
0 голосов
/ 11 декабря 2019

Можно использовать 2 группы захвата, а при замене использовать обе группы захвата \1\2

([A-Z_]+\[[^(\s]+)[^\S\r\n]*\([A-Z]+\)[^\S\r\n]*(\][A-Z_]+)

По частям

  • ( Захват группа 1
    • [A-Z_]+ Совпадение 1+ символов A-Z или _
    • \[[^(\s]+ Совпадение [ и 1+ любых символов, кроме перечисленных
  • ) Закрыть группу
  • [^\S\r\n]* Совпадение с 0+ пробельными символами, кроме новой строки
  • \([A-Z]+\) Совпадение с символами A-Z в скобках
  • [^\S\r\n]* Совпадение с 0+ пробелами кроме новой строки
  • ( Захват группа 2
    • \][A-Z_]+ Совпадение ] и 1+ символов A-Z или _
  • ) Закрыть группу

Regex demo | Python demo

Например

import re

regex = r"([A-Z_]+\[[^(\s]+)[^\S\r\n]*\([A-Z]+\)[^\S\r\n]*(\][A-Z_]+)"
test_str = "_AHDHDUHD[Tsfs (SGYA)]AHUDSHDI_"
print(re.sub(regex, r"\1\2", test_str))

Выход

_AHDHDUHD[Tsfs]AHUDSHDI_
...