Удаление текста в скобках (скобки в скобках prob)

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

sentence.gsub(/(.*?)/, "") 

и это отлично работает, пока у меня нет предложения, такого как:

"This is (a test (string))"

затем выше задыхается. Кто-нибудь знает, как это сделать? Я в полном замешательстве.

5 ответов


один подход заключается в замене вводных групп изнутри:

x = string.dup
while x.gsub!(/\([^()]*\)/,""); end
x

Похоже, вам нужно быть жадным, удалив ?

>> "This is (a test (string))".gsub(/\(.*\)/, "")
=> "This is "

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


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

однако, мы не говорим о регулярных выражениях здесь, мы про Regexps. Хотя их семантика и синтаксис (очень) свободно основаны на регулярных выражениях, они совершенно разные и особенно гораздо более мощные. В зависимости от конкретного вкуса Regexp вы используете, они могут или не могут выражать рекурсию и, таким образом, анализировать вложенные скобки. На Perl Regex, например can разбор вложенных скобок. Я не уверен, что Руби Regexp может, но мне все равно, потому что так, что Regexp более мощный чем регулярные выражения, как правило, достигается путем болтов все больше и больше синтаксиса на них.

это превращает регулярные выражения, которые призваны быть простыми, в непонятных монстров. (Если вы можете сказать с первого взгляда, что Perl Regex написал @Анон, тогда дерзайте. Но я не могу и поэтому предпочитаю им не пользоваться.)

Я предпочитаю использовать более мощный парсер, а не комплекс Regexp.

в этом случае, у вас есть контекстно-свободный язык, поэтому вы можете использовать очень простой рекурсивный спуск парсер. Вы можете еще больше упростить свой рекурсивный парсер спуска, обрабатывая те части, которые are regular с регулярным выражением. Наконец, если вы замените рекурсию в рекурсивном парсере спуска на итерацию + мутацию и разумно используете булеву семантику Ruby, весь парсер в основном конденсируется до этой единственной строки:

while str.gsub!(/\([^()]*?\)/, ''); end

Я не думаю, что это слишком плохой.

вот все это с некоторым дополнительным удалением дубликатов пробелов и (конечно) тестового набора:

require 'test/unit'
class TestParenthesesRemoval < Test::Unit::TestCase
  def test_that_it_removes_even_deeply_nested_parentheses
    str = 'This is (was?) some ((heavily) parenthesized (but not overly so 
          (I hope))) text with (superflous) parentheses: )(.'
    res = 'This is some text with parentheses: )(.'

    while str.gsub!(/\([^()]*?\)/, ''); end
    str.squeeze!(' ')

    assert_equal res, str
  end
end

следующее регулярное выражение Perl будет соответствовать сбалансированным скобкам:

/(\((?:[^\(\)]++|(?1))*\))/

однако к тому времени, когда Вы дойдете до этого момента, вы больше не используете "регулярные" выражения.


ответ jleedev будет работать, если на самом внешнем уровне есть только один набор скобок; в этом случае выражение для внутренностей этих скобок должно сделать трюк.

однако, и, возможно, немного удивительно, regexps, как определено в Perl, Java, Ruby и несколько других языков, но также grep и sed не подходит для решения этой проблемы. Нет регулярного выражения для работы с общим случаем вложенных разделителей. Это одна из причин, почему люди так кричат на вас, когда вы хотите использовать регулярное выражение для обработки HTML или XML.

интересно, что создатель языка Lua решил эту проблему, добавив новый соответствующий шаблон к довольно простому языку шаблонов. Посмотрите на нижнюю горсть строк в http://www.lua.org/pil/20.2.html !