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

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

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

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

"This is (a test (string))"

Затем вышеупомянутые дроссели. У кого-либо есть какая-либо идея, как сделать это? Я полностью озадачен.

6
задан Josh Lee 23 December 2009 в 02:42
поделиться

5 ответов

Один из вариантов - заменить изнутри скобки:

x = string.dup
while x.gsub!(/\([^()]*\)/,""); end
x
10
ответ дан 8 December 2019 в 05:21
поделиться

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

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

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

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

В этом случае у вас есть контекстно-свободный язык, поэтому вы можете использовать очень простой рекурсивный анализатор спуска. Вы можете еще больше упростить синтаксический анализатор рекурсивного спуска, обработав те части, которые являются регулярными, с помощью регулярного выражения. Наконец, если вы замените рекурсию в синтаксическом анализаторе рекурсивного спуска на итерацию + мутацию и грамотно воспользуетесь логической семантикой 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
2
ответ дан 8 December 2019 в 05:21
поделиться

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

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

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

10
ответ дан 8 December 2019 в 05:21
поделиться

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

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

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

1
ответ дан 8 December 2019 в 05:21
поделиться

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

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

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

.
0
ответ дан 8 December 2019 в 05:21
поделиться
Другие вопросы по тегам:

Похожие вопросы: