Regex: удалить содержимое квадратных скобок - PullRequest
2 голосов
/ 23 марта 2011

Существует ли регулярное выражение, которое можно использовать с поиском / заменой для удаления всего, что происходит в квадратных скобках (и скобках)?

Я пробовал \[.*\], который выбивает лишние вещи (например, "[chomps] extra [stuff]")

Кроме того, то же самое с ленивым соответствием \[.*?\] не работает, когда есть вложенная скобка (например, "stops [chomping [too] early]!")

Ответы [ 5 ]

11 голосов
/ 23 марта 2011

Попробуйте что-то вроде этого:

$text = "stop [chomping [too] early] here!";
$text =~ s/\[([^\[\]]|(?0))*]//g;
print($text);

, который напечатает:

stop  here!

Краткое объяснение:

\[            # match '['
(             # start group 1
  [^\[\]]     #   match any char except '[' and ']'
  |           #   OR
  (?0)        #   recursively match group 0 (the entire pattern!)
)*            # end group 1 and repeat it zero or more times
]             # match ']'

Выражение, приведенное выше, будет заменено напустая строка.

Вы можете проверить это онлайн: http://ideone.com/tps8t

РЕДАКТИРОВАТЬ

Как уже упоминалось @ridgerunner, вы можете сделать регулярное выражение более эффективным, сделав *и класс персонажа [^\[\]] совпадает один или несколько раз и , что делает его притяжательным , и даже путем создания группы без захвата из группы 1:

\[(?:[^\[\]]++|(?0))*+]

Но реальное улучшение скорости может быть заметно только при работе с большими струнами (вы можете проверить это, конечно!).

5 голосов
/ 23 марта 2011

Технически это невозможно с регулярными выражениями, потому что язык, который вы сопоставляете, не соответствует определению «регулярный».Существуют некоторые расширенные реализации регулярных выражений, которые могут сделать это в любом случае, используя рекурсивные выражения, среди них:

Грета:

http://easyethical.org/opensource/spider/regexp%20c++/greta2.htm#_Toc39890907

и

PCRE

http://en.wikipedia.org/wiki/Perl_Compatible_Regular_Expressions

См. "Рекурсивные шаблоны", в котором есть пример для скобок.

Рекурсивное совпадение скобок PCRE будет выглядеть следующим образом:

\[(?R)*\]

edit:

Поскольку вы добавили, что используете Perl, вот страница, которая явно описывает, как сопоставлять сбалансированные пары операторов в Perl:

http://perldoc.perl.org/perlfaq6.html#Can-I-use-Perl-regular-expressions-to-match-balanced-text%3f

что-то вроде:

$string =~ m/(\[(?:[^\[\]]++|(?1))*\])/xg;
4 голосов
/ 24 марта 2011

Поскольку вы используете Perl, вы можете использовать модули из CPAN и вам не нужно писать собственные регулярные выражения. Обратите внимание на модуль Text::Balanced, который позволяет извлекать текст из сбалансированных разделителей. Использование этого модуля означает, что если ваши разделители внезапно изменятся на {}, вам не нужно выяснять, как изменить регулярное выражение, нужно только изменить параметр разделителя в одном вызове функции.

3 голосов
/ 24 марта 2011

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

my $string = "stops [chomping [too] early]!";
# remove any [...] sequence that doesn't contain a [...] inside it
# and keep doing it until there are no [...] sequences to remove
1 while $string =~ s/\[[^\[\]]*\]//g; 
print $string;

1 while будетв основном ничего не делать, пока условие верно.Если s/// соответствует и удаляет раздел в скобках, цикл повторяется и s/// запускается снова.

Это будет работать, даже если вы используете более старую версию Perl или другой язык, который не поддерживает расширенный шаблон рекурсии (?0) в ответе Барта Киерса.

1 голос
/ 23 марта 2011

Вы хотите удалить только те вещи между [], которые сами не []. IE:

\[[^\]]*\]

Это довольно волосатый беспорядок [] s; -)

Это не будет обрабатывать несколько вложенных []. IE, соответствующий [foo [bar] baz] не будет работать.

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