Python 如何用正则表达式删除括号内的文本?

Python 如何用正则表达式删除括号内的文本?,python,regex,perl,Python,Regex,Perl,我正在尝试处理一堆文件,然后需要修改以删除文件名中的无关信息;值得注意的是,我试图删除括号内的文本。例如: filename = "Example_file_(extra_descriptor).ext" 和我想重排一整组文件,括号中的表达式可能在中间或结尾,长度可变。 正则表达式是什么样子的?最好使用Perl或Python语法 s/\([^)]*\)// 因此,在Python中,您将执行以下操作: re.sub(r'\([^)]*\)', '', filename) 如果您可以使用sed

我正在尝试处理一堆文件,然后需要修改以删除文件名中的无关信息;值得注意的是,我试图删除括号内的文本。例如:

filename = "Example_file_(extra_descriptor).ext"

和我想重排一整组文件,括号中的表达式可能在中间或结尾,长度可变。

正则表达式是什么样子的?最好使用Perl或Python语法

s/\([^)]*\)//
因此,在Python中,您将执行以下操作:

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

如果您可以使用
sed
(可能从您的程序中执行,它将非常简单:

sed 's/(.*)//g'
我将使用:

\([^)]*\)

如果路径可能包含括号,则
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'

如果您不一定需要使用正则表达式,可以考虑使用Perl删除括号

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;
}
你可能会想,“为什么一个正则表达式在一行中就完成了这一切?”

Text::Balanced处理嵌套括号。因此将正确提取
$filename='foo_ubar(baz)buz)).foo'
。此处提供的基于正则表达式的解决方案将在此字符串上失败。一只会在第一次关门时停下来,另一只会把它们全吃掉

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

   $filename =~ s/\(.*\)//;
   # returns 'foo_.foo'

   # text balanced example returns 'foo_).foo'
如果任何一种正则表达式行为都是可以接受的,请使用正则表达式——但要记录所做的限制和假设。

Java代码:

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

匹配括号中没有其他
字符的子字符串的模式是

详细信息

  • \(
    -开口圆形支架(注意,在POSIX BRE中,
    应使用,请参见下面的
    sed
    示例)
  • [^()]*
    -零个或更多字符(由于
    *
    )不是中定义的字符,即除
    以外的任何字符
  • \)
    -闭合圆括号(POSIX BRE中不允许逃逸)
删除代码段:

  • JavaScript
    string.replace(/\([^()]*\)/g',)
  • PHP
    preg\u 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(“\\([^()]*\\),”)
  • Ruby
    s.gsub(/\([^()]*\)/,“”)
  • R
    gsub(\\([^()]*\\),“”,x)
  • Lua
    string.gsub,“%([^()]*%”,“)
  • Bash/sed
    sed的/([^()]*)///g'
  • Tcl
    regsub-all{\([^()]*\)}$s”结果
  • C++
    std::regex
    std::regex\u替换(s,std::regex(R)(\([^()]*\))”,“”)
  • Objective-C
    NSRegularExpression*regex=[NSRegularExpression regular expression with pattern:@“\\([^()]*\\)选项:NSRegularExpression不区分大小写错误:&error];
    NSString*modifiedString=[regex StringByReplacingMatcheInstalling:string选项:0范围:NSMakeRange(0,[string length]),带模板:@”“];
  • Swift
    s.replacingOccurrences(of:“\\([^()]*\\)”,with:,options:[.regularExpression])

对于那些想使用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')

您只是将表达式
*
@Gumbo:不,他不是。在sed中,“\(…\)”groups.Ops,对不起。我不知道。有什么理由更喜欢。*?而不是[^)]*@Kip:nope。我不知道为什么,但是。*始终是我想到的第一件事。@Kip:.*不是由所有正则表达式分析器处理的,而您的[^]*几乎所有人都在处理。@Kip:另一个原因是回溯。*获取第一个左参数和最后一个右参数之间的所有内容:“a(b)c(d)e”将变为“ae”。[^)]*仅在第一个左参数和第一个右参数之间删除:“ac(d)e”。嵌套参数也会有不同的行为。虽然我知道不能用(经典)正则表达式解析嵌套括号,但如果知道永远不会遇到嵌套括号,可以将问题简化为可以用正则表达式完成的问题,而且相当容易。当我们不需要解析器工具时,使用它太过分了。@Chris Lutz-我应该在第一句中说“考虑”而不是“使用”。在很多情况下,正则表达式会起作用,这就是为什么我说如果行为可以接受,就使用正则表达式。你确定“额外描述符”不能包含“)”?如果可以的话,问题就变得更难了…@dmckee:如果paren可以嵌套就更难了,不过如果你只是想去掉第一个“(“和最后一个“)”之间的所有东西,那就不难了。只要用贪婪的“*”而不是“*?”。@j_random_hacker你是对的,这要困难得多,因为嵌套括号不能被FSM识别(你必须跟踪嵌套级别,它是无限的),因此不能被正则表达式识别。为了使其成为可能,您必须将自己限制在有限的嵌套级别。我已经想自己编写嵌套方括号删除程序,但您节省了我的时间,谢谢!
Pattern pattern1 = Pattern.compile("(\\_\\(.*?\\))");
System.out.println(fileName.replace(matcher1.group(1), ""));
\([^()]*\)
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')