Как удалить текст в скобках с помощью регулярного выражения?

Я пытаюсь обработать кучу файлов, и мне нужно изменить, чтобы удалить постороннюю информацию в именах файлов; в частности, я пытаюсь удалить текст внутри скобок. Например:

filename = "Example_file_(extra_descriptor).ext"

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

Как будет выглядеть регулярное выражение? Предпочтительным будет синтаксис Perl или Python.

9 ответов


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

Итак, в Python вы бы сделали:

re.sub(r'\([^)]*\)', '', filename)

Я хотел бы использовать:

\([^)]*\)

шаблон, который соответствует подстрокам в paretheses нет ( и ) символы между (как (xyz 123) на Text (abc(xyz 123)) is

\([^()]*\)

подробности:

  • \( - открывающий круглый кронштейн (обратите внимание, что в POSIX BRE,( следует использовать, см. sed пример ниже)
  • [^()]* - ноль или больше (из-за * kleene star quantifier) персонажей кроме те, которые определены в отрицается класс символов/выражение скобки POSIX, то есть любые символы, кроме ( и )
  • \) - закрывающий круглый кронштейн (не экранирование в POSIX BRE разрешено)

удаление фрагментов кода:

  • JavaScript: string.replace(/\([^()]*\)/g, '')
  • PHP: preg_replace('~\([^()]*\)~', '', $string)
  • Perl: $s =~ s/\([^()]*\)//g
  • Python: re.sub(r'\([^()]*\)', '', s)
  • C#: Regex.Replace(str, @"\([^()]*\)", string.Empty)
  • VB.NET:Regex.Replace(str, "\([^()]*\)", "")
  • Java: s.replaceAll("\([^()]*\)", "")
  • Рубин: s.gsub(/\([^()]*\)/, '')
  • R: gsub("\([^()]*\)", "", x)
  • Луа: string.gsub(s, "%([^()]*%)", "")
  • Bash / sed: sed 's/([^()]*)//g'
  • на TCL: regsub -all {\([^()]*\)} $s "" result
  • C++ std::regex: std::regex_replace(s, std::regex(R"(\([^()]*\))"), "")
  • С:
    NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"\([^()]*\)" options:NSRegularExpressionCaseInsensitive error:&error]; NSString *modifiedString = [regex stringByReplacingMatchesInString:string options:0 range:NSMakeRange(0, [string length]) withTemplate:@""];

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

use Text::Balanced qw(extract_bracketed);

my ($extracted, $remainder, $prefix) = extract_bracketed( $filename, '()', '[^(]*' );

{   no warnings 'uninitialized';

    $filename = (defined $prefix or defined $remainder)
                ? $prefix . $remainder
                : $extracted;
}

вы можете думать: "зачем все это делать, когда регулярное выражение делает трюк в одной строке?"

$filename =~ s/\([^}]*\)//;

Text:: Balanced обрабатывает вложенные скобки. Так что $filename = 'foo_(bar(baz)buz)).foo' будет извлечено правильно. Решения на основе регулярных выражений, предлагаемые здесь, не будут работать в этой строке. Один остановится на первом закрытии парен, а другой съест их всех.

$filename =~ s / ([^}]*)//; # returns ' foo_buz)).foo'

$filename =~ s/(.*)//; # следующие файлы-foo_ возвращает.foo'

# text balanced example возвращает ' foo_).foo'

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


Если путь может содержать круглые скобки, то r'\(.*?\)' regex недостаточно:

import os, re

def remove_parenthesized_chunks(path, safeext=True, safedir=True):
    dirpath, basename = os.path.split(path) if safedir else ('', path)
    name, ext = os.path.splitext(basename) if safeext else (basename, '')
    name = re.sub(r'\(.*?\)', '', name)
    return os.path.join(dirpath, name+ext)

по умолчанию функция сохраняет заключенные в скобки фрагменты в каталог и части расширения пути.

пример:

>>> f = remove_parenthesized_chunks
>>> f("Example_file_(extra_descriptor).ext")
'Example_file_.ext'
>>> path = r"c:\dir_(important)\example(extra).ext(untouchable)"
>>> f(path)
'c:\dir_(important)\example.ext(untouchable)'
>>> f(path, safeext=False)
'c:\dir_(important)\example.ext'
>>> f(path, safedir=False)
'c:\dir_\example.ext(untouchable)'
>>> f(path, False, False)
'c:\dir_\example.ext'
>>> f(r"c:\(extra)\example(extra).ext", safedir=False)
'c:\\example.ext'

Если вы можете стоять, чтобы использовать sed (возможно, выполнить из вашей программы, это было бы так же просто, как:

sed 's/(.*)//g'

>>> import re
>>> filename = "Example_file_(extra_descriptor).ext"
>>> p = re.compile(r'\([^)]*\)')
>>> re.sub(p, '', filename)
'Example_file_.ext'

Java-кода:

Pattern pattern1 = Pattern.compile("(\_\(.*?\))");
System.out.println(fileName.replace(matcher1.group(1), ""));

для тех, кто хочет использовать Python, вот простая процедура, которая удаляет скобки подстроки, в том числе с вложенными скобками. Ладно, это не регулярное выражение, но оно сделает свою работу!

def remove_nested_parens(input_str):
    """Returns a copy of 'input_str' with any parenthesized text removed. Nested parentheses are handled."""
    result = ''
    paren_level = 0
    for ch in input_str:
        if ch == '(':
            paren_level += 1
        elif (ch == ')') and paren_level:
            paren_level -= 1
        elif not paren_level:
            result += ch
    return result

remove_nested_parens('example_(extra(qualifier)_text)_test(more_parens).ext')