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


77

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

filename = "Example_file_(extra_descriptor).ext"

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

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


您确定“ extra_descriptor”不能包含“)”吗?如果可以的话,问题将变得更加棘手...
dmckee ---前主持人小猫

1
@dmckee:如果可以嵌套paren会比较困难,但是如果您只想摆脱第一个'('和最后一个')'之间的所有内容,这并不困难:只需使用贪婪的'。*'即可'。*?'。
j_random_hacker

2
@j_random_hacker是的,这很难做,因为嵌套括号不能用FSM识别(您必须跟踪嵌套级别,而嵌套级别是无限的),因此不能通过正则表达式识别。为了使它成为可能,您必须将自己限制在有限的嵌套级别。
2015年

Answers:


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

因此,在Python中,您可以这样做:

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

2
有什么理由喜欢。*吗?[^)] *
基普(Kip)2009年

@Kip:不。我不知道为什么,但是。*始终是我想到的第一件事。
Can BerkGüder09年

@Kip:。*?不是所有的正则表达式解析器都处理,而您的[^)] *几乎全部由它们处理。
X-Istence 09年

@Kip:另一个原因是回溯。
Gumbo

13
。*获取第一个左括号和最后一个右括号之间的所有内容:“ a(b)c(d)e”将变为“ ae”。[^)] *仅在第一个左括号和第一个右括号之间删除:“ ac(d)e”。您还将获得嵌套paren的不同行为。
daotoad

66

在括号匹配子串的图案不具有其他()字符之间(如(xyz 123)Text (abc(xyz 123))是

\([^()]*\)

详细资料

删除代码段:

  • JavaScriptstring.replace(/\([^()]*\)/g, '')
  • PHP的preg_replace('~\([^()]*\)~', '', $string)
  • Perl$s =~ s/\([^()]*\)//g
  • Pythonre.sub(r'\([^()]*\)', '', s)
  • C#Regex.Replace(str, @"\([^()]*\)", string.Empty)
  • VB.NETRegex.Replace(str, "\([^()]*\)", "")
  • Java的s.replaceAll("\\([^()]*\\)", "")
  • 红宝石s.gsub(/\([^()]*\)/, '')
  • Rgsub("\\([^()]*\\)", "", x)
  • 卢阿string.gsub(s, "%([^()]*%)", "")
  • 重击/ sedsed 's/([^()]*)//g'
  • Tclregsub -all {\([^()]*\)} $s "" result
  • C ++std::regexstd::regex_replace(s, std::regex(R"(\([^()]*\))"), "")
  • 目标-C
    NSRegularExpression *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])


6

如果你不绝对需要使用正则表达式,使用考虑使用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;
}

您可能会想,“当正则表达式在一行中完成花样操作时,为什么要做所有这一切?”

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

Text :: Balanced处理嵌套的括号。因此$filename = 'foo_(bar(baz)buz)).foo'将被正确提取。此处提供的基于正则表达式的解决方案在此字符串上将失败。一个会停在第一个封闭的paren,另一个会全部吃光。

$ filename =〜s /([[^}] *)//; #返回'foo_buz))。foo'

$ filename =〜s /(.*)//; #返回'foo_.foo'

#文本平衡示例返回'foo _)。foo'

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


虽然我知道您无法使用(经典)正则表达式来解析嵌套括号,但是如果您永远都不会遇到嵌套括号,则可以将问题简化为可以使用正则表达式来完成的问题,并且相当容易。当我们不需要解析器工具时,这是过头的。
克里斯·卢兹

@Chris Lutz-我应该在第一句话中说“考虑”而不是“使用”。在许多情况下,使用正则表达式即可胜任,这就是为什么我说如果行为可以接受则使用正则表达式。
daotoad

3

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

2

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

我已经想自己写嵌套的括号删除器,但是您可以节省时间,谢谢!😊
AivanF。

1

如果您愿意使用sed(可能在程序内执行),那么它就很简单:

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

您只是将表达式分组.*
Gumbo

@Gumbo:不,他不是。在sed中,“ \(... \)”组。
runrig

抱歉 不知道
Gumbo

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.