регулярное выражение perl вынимает текст, заключенный в скобки - PullRequest
0 голосов
/ 03 июля 2011

как мне использовать Perl, чтобы избавиться от текста в скобках?Например: $ str = "Это строка (дополнительный материал)."
to $ str = "Это строка."

Я сейчас использую это, но оно не работает: $ str = ~ s / (([^)] +)) //;

Спасибо!

Ответы [ 7 ]

7 голосов
/ 03 июля 2011

Вы должны избежать скобок, например:

s/\([^)]*\)//g

Обновление по многочисленным просьбам:

Чтобы удалить пробел, вы можете просто удалить пробелы перед скобками. Это будет работать в большинстве случаев:

s/\s*\([^)]*\)//g

Для обработки вложенных скобок вы можете использовать рекурсивный шаблон, например так:

s/\s*\((?:[^()]+|(?R))*\)//g

Вы можете прочитать о (?R) и т.п. в perlre .

Последнее выражение будет работать для строки наподобие aaa (foo(b,a,2*(3+4)) b) (c (c) c) ddd (x)., давая aaa ddd..

1 голос
/ 03 июля 2011

Ни одно из решений на данный момент не делает того, о чем спрашивал ОП.

  • Выражение $str =~ s/\([^)]*\)//g;

    • Преобразование "Это (дополнительный материал)string "to" Это строка ", оставляющая два пробела между" a "и" string ".
    • Преобразует" Это (двоякая (вложенная)) строка "в" Это строка) ".
    • Преобразует "Это (строка с двойным (нет, (трижды!) Вложенным) выражением))" в "Это вложенное) выражение) строкой".
  • Подобные проблемы существуют с $str =~ s/[ ]?\(.*?\)[ ]?//g; И зачем использовать эти квадратные скобки?Разве регулярные выражения не достаточно волосатые без лишних вещей?

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

1 while $str =~ s/(\w?)(\s*)\([^()]*\)(\s*)(\w?)
                 /($1&&$4)?($1.($2?$2:$3).$4):($1?$1:$4)/ex;

Редактировать
Результаты испытаний:

'This string is OK as is.' -> 'This string is OK as is.'
'This is a (extra stuff) string.' -> 'This is a string.'
'(Preliminary remark)  string' -> 'string'
'String (with end remark)' -> 'String'
'A string (remark before punctuation)!' -> 'A string!'
'A (doubly (nested)) string' -> 'A string'
'A (doubly (no, (triply!) nested)) string' -> 'A string'

Редактировать2
exgквалификация приводит к неправильной обработке «This (delete) (delete) является строкой».Все, что нужно, это ex.

1 голос
/ 03 июля 2011

(являются специальными и должны быть экранированы

s/\([^)]+\)//g
0 голосов
/ 04 июля 2011

Сплит версия. Я вроде как разделяю для этого, потому что это неинвазивно, сохраняя оригинальный формат, а также, регулярные выражения становятся ... сложными. Хотя, конечно, вам нужно регулярное выражение, чтобы урезать его.

Тебе все еще нужно проработать интервал. Не просто предсказать, появится ли дополнительное пространство в передней части или в конце, и удаление всех двойных пробелов не сохранит исходный формат. Это решение удаляет единственное пространство перед открывающимися скобками и ничего больше. Работает в большинстве случаев, предполагая, что ввод имеет правильную пунктуацию для начала.

use warnings;
use strict;

while (<DATA>) {
    my @parts = split /\(/;
    print de_paren(@parts);
}

sub de_paren {
    my $return = shift;
    my @parts = @_;
    while (my $word = shift @parts) {
        next unless $word =~ /\)/;
        $word =~ s/^.*?\)// while ($word =~ /\)/);
        $return =~ s/ $//;
        $return .= $word;
    }
    return $return;
}

__DATA__
A (doubly (no, (triply!) nested)) string
This is a (extra stuff) string.
(Preliminary remark)  string
String (with end remark) String (with end remark)
A string (remark before punctuation)!
A (doubly (nested)) string

Вывод:

A string
This is a string.
  string
String String
A string!
A string ->
0 голосов
/ 03 июля 2011

Хм. Я ожидал, что «жадный» принцип будет применен, он будет питаться до самых близких скобок, даже когда вложен.Возможно, немного грубой силы, использующей функции index и rindex, было бы лучше.

Но я все еще задаюсь вопросом, почему бы

$str =~ s/[ ]?\(.*?\)[ ]?//g;

не перебить его полностью до последнего ')«

0 голосов
/ 03 июля 2011

Я конвертирую специальные символы в шестнадцатеричные для удобства использования в моем регулярном выражении

/\x28([^\x29]+)\x29/
0 голосов
/ 03 июля 2011

Эта строка должна делать то, что вам нужно:

$str =~ s/[ ]?\(.*?\)[ ]?//g;

Обратите внимание, что он не будет работать с вложенными скобками (например, (этим)), поскольку регулярное выражение должно быть намного сложнее для этого типа функциональности.

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