Удалить текст между () и [] в Python
У меня есть очень длинная строка текста с ()
а также []
в этом. Я пытаюсь удалить символы между скобками и скобками, но не могу понять, как это сделать.
Список похож на это:
x = "This is a sentence. (once a day) [twice a day]"
Этот список не тот, с которым я работаю, но он очень похож и намного короче.
Спасибо за помощь.
9 ответов
Это должно работать для паренов. регулярные выражения будут "потреблять" соответствующий текст, поэтому не будут работать с вложенными паренами.
import re
regex = re.compile(".*?\((.*?)\)")
result = re.findall(regex, mystring)
или это найдет один набор паренов... просто цикл, чтобы найти больше
start = mystring.find( '(' )
end = mystring.find( ')' )
if start != -1 and end != -1:
result = mystring[start+1:end]
Вы можете использовать функцию re.sub.
>>> import re
>>> x = "This is a sentence. (once a day) [twice a day]"
>>> re.sub("([\(\[]).*?([\)\]])", "\g<1>\g<2>", x)
'This is a sentence. () []'
Если вы хотите удалить [] и (), вы можете использовать этот код:
>>> import re
>>> x = "This is a sentence. (once a day) [twice a day]"
>>> re.sub("[\(\[].*?[\)\]]", "", x)
'This is a sentence. '
Важно: этот код не будет работать с вложенными символами
Запустите этот скрипт, он работает даже с вложенными скобками.
Использует базовые логические тесты.
def a(test_str):
ret = ''
skip1c = 0
skip2c = 0
for i in test_str:
if i == '[':
skip1c += 1
elif i == '(':
skip2c += 1
elif i == ']' and skip1c > 0:
skip1c -= 1
elif i == ')'and skip2c > 0:
skip2c -= 1
elif skip1c == 0 and skip2c == 0:
ret += i
return ret
x = "ewq[a [(b] ([c))]] This is a sentence. (once a day) [twice a day]"
x = a(x)
print x
print repr(x)
Просто если вы не запускаете его,
Вот вывод:
>>>
ewq This is a sentence.
'ewq This is a sentence. '
Вот решение, похожее на ответ @pradyunsg (оно работает с произвольными вложенными скобками):
def remove_text_inside_brackets(text, brackets="()[]"):
count = [0] * (len(brackets) // 2) # count open/close brackets
saved_chars = []
for character in text:
for i, b in enumerate(brackets):
if character == b: # found bracket
kind, is_close = divmod(i, 2)
count[kind] += (-1)**is_close # `+1`: open, `-1`: close
if count[kind] < 0: # unbalanced bracket
count[kind] = 0 # keep it
else: # found bracket to remove
break
else: # character is not a [balanced] bracket
if not any(count): # outside brackets
saved_chars.append(character)
return ''.join(saved_chars)
print(repr(remove_text_inside_brackets(
"This is a sentence. (once a day) [twice a day]")))
# -> 'This is a sentence. '
Вы можете разделить, отфильтровать и снова присоединить строку. Если ваши скобки четко определены, подойдет следующий код.
import re
x = "".join(re.split("\(|\)|\[|\]", x)[::2])
Вы можете попробовать это. Можно удалить скобку, и внутри нее будет существовать содержимое.
import re
x = "This is a sentence. (once a day) [twice a day]"
x = re.sub("\(.*?\)|\[.*?\]","",x)
print(x)
Ожидаемый результат:
This is a sentence.
Для тех, кто ценит простоту принятого ответа jvallver и ищет более читабельный код:
>>> import re
>>> x = 'This is a sentence. (once a day) [twice a day]'
>>> opening_braces = '\(\['
>>> closing_braces = '\)\]'
>>> non_greedy_wildcard = '.*?'
>>> re.sub(f'[{opening_braces}]{non_greedy_wildcard}[{closing_braces}]', '', x)
'This is a sentence. '
Большая часть объяснения того, почему это регулярное выражение работает, включена в код. Ваше будущее «я» поблагодарит вас за 3 дополнительные строки.
(Замените f-строку на эквивалентную конкатенацию строк для совместимости с Python2)
регулярное выражение\(.*?\)|\[.*?\]
удаляет содержимое скобок, находя пары, сначала удаляет скобки, а затем квадратные скобки. I также отлично работает для вложенных скобок, поскольку действует последовательно. Конечно, это сломается в случае сценария с плохими скобками.
_brackets = re.compile("\(.*?\)|\[.*?\]")
_spaces = re.compile("\s+")
_b = _brackets.sub(" ", "microRNAs (miR) play a role in cancer ([1], [2])")
_s = _spaces.sub(" ", _b.strip())
print(_s)
# OUTPUT: microRNAs play a role in cancer
Решение без регулярного выражения, которое не заботится о сбалансированных круглых скобках (слева направо соответствует ближайшей открытой закрывающей паре) и добавляет остатки в конец, если они незакрыты, и немедленно начинает удалять символы, если они находятся после открывающих круглых скобок, независимо от их числа. предыдущих закрывающихся скобок.
def removeparenthesis(input_str, open_p="(", close_p=")"):
result = ''
remainder = ''
paren_level = 0
for ch in input_str:
if ch in open_p:
if paren_level < 0:
paren_level = 1
else:
paren_level += 1
elif ch in close_p:
paren_level -= 1
remainder = ''
elif 0 >= paren_level:
result += ch
else:
remainder += ch
return result + remainder
Я считаю, что это немного более естественно, чем заставлять все быть сбалансированным. Сделаны очень закрывающие круглые скобки для игнорирования в тексте в обычном режиме.
Полезно, если ваш вариант использования удаляет круглые скобки и их содержимое, чтобы не остаться неуклюжими, не имеющими себе равных. «Безопасный» способ вызвать это, вероятно, - это два вызова, один для каждой пары, а не один для обеих пар, поскольку я не нашел способа, который мне нравился бы делать оба без сопоставления (] или аналогичного, даже если опция там.