提取方括号中的文本的正则表达式

621

简单的正则表达式问题。我的字符串格式如下:

this is a [sample] string with [some] special words. [another one]

正则表达式提取方括号内的单词,即:

sample
some
another one

注意:在我的使用情况中,括号不能嵌套。

15个回答

1110

你可以全局使用以下正则表达式:

\[(.*?)\]

解释:

  • \[[ 是元字符,如果你想要匹配它的字面意思,需要转义。
  • (.*?):以非贪婪的方式匹配并捕获所有内容。
  • \]] 是元字符,如果你想要匹配它的字面意思,需要转义。

13
另一个回答的方法是使用[^]],它比非贪婪(?)更快,并且适用于不支持非贪婪的正则表达式。然而,非贪婪看起来更好看。 - Ipsquiggle
255
如何在输出结果中排除 [] 符号? - Mickey Tin
14
@MickeyTin,如果你正在使用Java,你可以使用group(1)而不是group()来对其进行分组,这样'[]'就不会一起出现了。 - andolffer.joseph
28
仅匹配第一次出现 - hfatahi
20
如何在返回值中剔除括号? - jzadra
显示剩余14条评论

220
(?<=\[).+?(?=\])

将不带括号的内容捕获

  • (?<=\[) - 正向后瞻,匹配左方括号[

  • .*? - 匹配非贪婪模式下的内容

  • (?=\]) - 正向前瞻,匹配右方括号]

编辑:对于嵌套括号,以下正则表达式应该可以解决:

(\[(?:\[??[^\[]*?\]))

4
我已经检查过了,它是有效的。然而,在不支持反向预查的环境中,比如JavaScript,它将无法工作。也许这就是你的情况? - Adam Moszczyński
Adam,当字符串中有 . 时,你的嵌套括号解决方案会失败... - patrick
5
写这些正则表达式的人真是个神奇的魔术师。非常感谢你们! - Ivan Yurchenko
3
应该接受这个答案,因为提问者特别注明输出时不带括号。目前被接受的答案会返回 [ '[sample]', '[some]', '[another one]' ],而这个答案会返回 [ 'sample', 'some', 'another one' ] - iandllnghm
这是正确的答案。 - Ulf Aslak
显示剩余2条评论

104

这应该可以正常工作:

\[([^]]+)\]

7
在我的使用情境中,括号内的文本可能会包含换行符,而这个正则表达式可行,而被接受的答案则不行。 - Dave
1
字符类 [^]] 的含义是什么?它匹配什么? - Richard
3
@Richard,^ 取消了字符类。它表示“任何不是 ] 的字符”。 - jasonbar
9
我认为它的效果不如预期,你应该使用\[([^\[\]]*)\]来获取最内层括号中的内容。如果你查看lfjlksd [ded[ee]22],那么\[([^]]+)\]将会得到[ded[ee],而建议使用的表达式将返回[ee]。在链接中测试过。 - TMC
2
请提供使用此正则表达式并提取文本的'sed'和'awk'示例。谢谢。 - valentt
显示剩余3条评论

40

括号可以嵌套吗?

如果不能: \[([^]]+)\] 匹配一个项,包括方括号。反向引用 \1 将包含要匹配的项目。如果你的正则表达式支持环视,请使用。

(?<=\[)[^]]+(?=\])

这只会匹配括号内的项目。


1
@KunalMukherjee:不,正则表达式可以匹配任意次数。但是有些正则表达式需要明确告知要重复应用正则表达式(例如,在JavaScript中使用“/g”标志)。 - Tim Pietzcker

34

要匹配位于第一个左方括号 [ 和最后一个右方括号 ] 之间的子字符串,您可以使用

\[.*\]            # Including open/close brackets
\[(.*)\]          # Excluding open/close brackets (using a capturing group)
(?<=\[).*(?=\])   # Excluding open/close brackets (using lookarounds)

查看 正则表达式演示正则表达式演示 #2

使用以下表达式来匹配字符串在最近的方括号之间

  • 包括方括号:

  • \[[^][]*] - PCRE、Python re/regex、.NET、Golang、POSIX(grep、sed、bash)

  • \[[^\][]*] - ECMAScript(JavaScript、C++ std::regex、VBA RegExp

  • \[[^\]\[]*] - Java、ICU regex

  • \[[^\]\[]*\] - Onigmo(Ruby,需要在所有地方转义括号)

  • 不包括方括号:

  • (?<=\[)[^][]*(?=]) - PCRE、Python re/regex、.NET(C#等)、JGSoft Software

  • \[([^][]*)] - BashGolang - 使用一对未转义的括号捕获方括号之间的内容,也请参见下面的内容

  • \[([^\][]*)] - JavaScriptC++ std::regexVBA RegExp

  • (?<=\[)[^\]\[]*(?=]) - Java regex、ICU(R stringr

  • (?<=\[)[^\]\[]*(?=\]) - Onigmo(Ruby,需要在所有地方转义括号)

注意*匹配0个或多个字符,请使用+匹配1个或多个字符以避免在结果列表/数组中出现空字符串匹配。

每当同时支持lookaround的时候,上述解决方案会依靠它们来排除前/后导开/闭括号。否则,依靠捕获组(某些语言的常见解决方案链接已提供)。
如果您需要匹配嵌套的括号,可以查看Regular expression to match balanced parentheses线程中的解决方案,并将圆括号替换为方括号以获得所需的功能。您应该使用捕获组来访问内容,并排除开/闭括号:

这个\[((?>[^][]+|(?<o>)\[|(?<-o>]))*)]已经满足了我99.9%的需求。我的意思是,我需要最外层括号内的所有内容,但不包括括号本身。例如,在你的.Net演示链接中,它匹配了[text [2]]的所有内容,而我希望匹配返回"text [2]"。然而,我可以通过获取匹配项并执行简单的子字符串来跳过第一个和最后一个字符来解决这个问题。我很好奇是否有可能稍微修改一下这个正则表达式以自动省略最外层的括号。 - B.O.B.
1
@B.O.B. 你需要获取第一组的值,请参见在线C#演示 - Wiktor Stribiżew
谢谢!我会在我正在使用的演示代码中尝试(在将其移入实际项目之前)。编辑:就是这样!感谢您专业和异常迅速的回复。 - B.O.B.

25

如果您不想在匹配中包含方括号,可以使用以下正则表达式:(?<=\[).*?(?=\])

让我们拆分它

. 匹配除行终止符之外的任何字符。 ?= 是一个正向预查。 正向预查在其后跟随特定字符串时查找字符串。 ?<=正向回顾。 正向回顾在其前面有特定字符串时查找字符串。引用这里的话:

正向预查 (?=)

查找 expression B 跟随 expression A 的位置:

A(?=B)

正向回顾 (?<=)

查找 expression B 前面的 expression A 的位置:

(?<=B)A

备选方案

如果您的正则表达式引擎不支持预查和回顾,则可以使用正则表达式 \[(.*?)\]捕获方括号中间的内容,并根据需要操作该组。

这个正则表达式如何工作?

括号将字符捕获到一个组中。 .*?以非贪婪的方式获取括号之间的所有字符(除非启用s标志,否则不包括行终止符)。


请注意,如果Safari版本小于16.4,则此代码会导致Safari崩溃-https://caniuse.com/js-regexp-lookbehind - Tonni

20

如果你可能有过不平衡的括号,你可以使用类似递归的表达式进行设计。

\[(([^\]\[]+)|(?R))*+\]

当然,这与您可能正在使用的语言或正则表达式引擎有关。

正则表达式演示1


除此之外,

\[([^\]\[\r\n]*)\]

正则表达式演示2

或者,

(?<=\[)[^\]\[\r\n]*(?=\])

RegEx演示3

是探索的好选择。


如果您希望简化/修改/探索表达式,则可以在regex101.com的右上面板中进行解释。如果愿意,您还可以在此链接中观看如何对一些示例输入进行匹配。


正则电路

jex.im用可视化方式展示正则表达式:

enter image description here

测试

const regex = /\[([^\]\[\r\n]*)\]/gm;
const str = `This is a [sample] string with [some] special words. [another one]
This is a [sample string with [some special words. [another one
This is a [sample[sample]] string with [[some][some]] special words. [[another one]]`;
let m;

while ((m = regex.exec(str)) !== null) {
    // This is necessary to avoid infinite loops with zero-width matches
    if (m.index === regex.lastIndex) {
        regex.lastIndex++;
    }
    
    // The result can be accessed through the `m`-variable.
    m.forEach((match, groupIndex) => {
        console.log(`Found match, group ${groupIndex}: ${match}`);
    });
}

来源

匹配平衡括号的正则表达式


这个回答被低估了,因为它提供了关于有限状态机的教育和强大能力的体验。 - Gr3go

13

(?<=\[).*?(?=\]) 根据上面的解释运行良好。以下是Python示例:

import re 
str = "Pagination.go('formPagination_bottom',2,'Page',true,'1',null,'2013')"
re.search('(?<=\[).*?(?=\])', str).group()
"'formPagination_bottom',2,'Page',true,'1',null,'2013'"

1
无论正则表达式出现在何处,您都应该始终使用代码格式。如果正则表达式出现在文本中而不是代码块中,则可以使用反引号对其进行格式化。(参考) - Alan Moore
1
此外,问题是关于方括号([])而不是圆括号的。 - Alan Moore

11

这里是@Tim Pietzcker的回答,链接

(?<=\[)[^]]+(?=\])

这几乎是我一直在寻找的答案。但是有一个问题,在一些旧版浏览器中可能无法支持正向后行断言。

所以我必须自己解决:)我设法写出了以下内容:

/([^[]+(?=]))/g

也许这会对某些人有所帮助。

console.log("this is a [sample] string with [some] special words. [another one]".match(/([^[]+(?=]))/g));


我正在寻找的完美答案。 - Asanka Siriwardena
太棒了!非常好的使用代码片段来展示它的工作原理。非常好的答案。 - Joshua Pinter

6

如果您想在方括号a-z之间仅过滤小写字母

(\[[a-z]*\])

如果您想要使用小写字母和大写字母a-zA-Z

(\[[a-zA-Z]*\]) 

如果你想要小型大写字母和数字 a-zA-Z0-9。
(\[[a-zA-Z0-9]*\]) 

如果您想要方括号内的所有内容

如果您想要文字、数字和符号

(\[.*\])

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接