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

Posted

技术标签:

【中文标题】如何使用正则表达式删除括号内的文本?【英文标题】:How can I remove text within parentheses with a regex? 【发布时间】:2010-10-13 00:06:53 【问题描述】:

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

filename = "Example_file_(extra_descriptor).ext"

我想对一大堆文件进行正则表达式,其中括号表达式可能位于中间或末尾,并且长度可变。

正则表达式会是什么样子?首选 Perl 或 Python 语法。

【问题讨论】:

您确定“extra_descriptor”不能包含“)”吗?如果可以的话,问题会变得更加困难...... @dmckee:如果括号可以嵌套,那就更难了,但如果你只想摆脱第一个'('和最后一个')'之间的所有内容这并不难:只需使用贪婪的 '.*' 而不是 '.*?'。 @j_random_hacker 你是对的,因为嵌套括号不能被 FSM 识别(你必须跟踪嵌套级别,这是无限的),所以这要困难得多。一个正则表达式。为了使这成为可能,您必须将自己限制在有限的嵌套级别。 【参考方案1】:
s/\([^)]*\)//

所以在 Python 中,你会这样做:

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

【讨论】:

有什么理由更喜欢 .*?超过 [^)]* @Kip:不。我不知道为什么,但 .* 总是首先想到的。 @Kip: .*?并非由所有正则表达式解析器处理,而您的 [^)]* 几乎由所有正则表达式解析器处理。 @Kip:另一个原因是回溯。 .* 获取第一个左括号和最后一个右括号之间的所有内容:'a(b)c(d)e' 将变为 'ae'。 [^)]* 仅在第一个左括号和第一个右括号之间删除:'ac(d)e'。您还将获得嵌套括号的不同行为。【参考方案2】:

匹配括号中的子字符串的模式之间没有其他()字符(如Text (abc(xyz 123)中的(xyz 123))是

\([^()]*\)

详情

\( - 一个左圆括号(请注意,在 POSIX BRE 中,应使用 (,参见下面的 sed 示例) [^()]* - 零个或多个(由于* Kleene star quantifier)字符除了negated character class/POSIX bracket expression 中定义的那些字符,即除() 之外的任何字符 \) - 右圆括号(POSIX BRE 中不允许转义)

删除代码sn-ps:

JavaScriptstring.replace(/\([^()]*\)/g, '') PHPpreg_replace('~\([^()]*\)~', '', $string) Perl$s =~ s/\([^()]*\)//g Pythonre.sub(r'\([^()]*\)', '', s) C#Regex.Replace(str, @"\([^()]*\)", string.Empty) VB.NETRegex.Replace(str, "\([^()]*\)", "") Javas.replaceAll("\\([^()]*\\)", "") 鲁比s.gsub(/\([^()]*\)/, '') Rgsub("\\([^()]*\\)", "", x) Luastring.gsub(s, "%([^()]*%)", "") Bash/sedsed 's/([^()]*)//g' Tclregsub -all \([^()]*\) $s "" result C++ std::regexstd::regex_replace(s, std::regex(R"(\([^()]*\))"), "") Objective-CNSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"\\([^()]*\\)" options:NSRegularExpressionCaseInsensitive error:&error]; NSString *modifiedString = [regex stringByReplacingMatchesInString:string options:0 range:NSMakeRange(0, [string length]) withTemplate:@""]; 斯威夫特s.replacingOccurrences(of: "\\([^()]*\\)", with: "", options: [.regularExpression])

【讨论】:

亲爱的 Wiktor 我只有一个问题。如果我们要排除括号 [ 而不是括号,我们是否必须在 [^ ] 结构中转义它们,如 [^\\[\\]] 或者它不需要像其他字符一样? @AnoushiravanR 这取决于正则表达式的风格。见this answer of mine。【参考方案3】:

我会使用:

\([^)]*\)

【讨论】:

【参考方案4】:

如果您不是绝对需要使用正则表达式,使用考虑使用 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/\(.*\)//;
   # returns 'foo_.foo'

   # text balanced example returns 'foo_).foo'

如果任一正则表达式行为是可接受的,请使用正则表达式——但要记录限制和所做的假设。

【讨论】:

虽然我知道你不能用(经典)正则表达式解析嵌套括号,但如果你知道你永远不会遇到嵌套括号,你可以将问题简化为可以用正则表达式完成的问题,而且相当容易。当我们不需要它时使用解析器工具是多余的。 @Chris Lutz - 我应该在第一句话中说“考虑”而不是“使用”。在许多情况下,正则表达式会完成这项工作,这就是为什么我说如果行为可以接受就使用正则表达式。【参考方案5】:

如果路径可能包含括号,那么 r'\(.*?\)' 正则表达式是不够的:

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'

【讨论】:

【参考方案6】:

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

【讨论】:

【参考方案7】:

如果您可以使用sed(可能在您的程序中执行,它会很简单:

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

【讨论】:

你只是对表达式.*进行分组。 @Gumbo:不,他不是。在 sed 中,"\(...\)" 组。【参考方案8】:
>>> import re
>>> filename = "Example_file_(extra_descriptor).ext"
>>> p = re.compile(r'\([^)]*\)')
>>> re.sub(p, '', filename)
'Example_file_.ext'

【讨论】:

【参考方案9】:

Java 代码:

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

【讨论】:

以上是关于如何使用正则表达式删除括号内的文本?的主要内容,如果未能解决你的问题,请参考以下文章

正则表达式查找字符串中大括号内的任何标签

用于匹配嵌套括号内的特定文本的 C# 正则表达式

正则表达式用于匹配 img 标记的开始和结束尖括号内的所有文本

需要正则表达式来删除括号[关闭]

正则表达式获取方括号之间的文本,包括差异?

怎么通过正则表达删除含中文的括号部分但保留含英文的括号部分?