花括号中间的字符串正则表达式

153

很不幸,我已经尝试过至少一年学习正则表达式,但由于使用频率太低而总是忘记。今年我的新年决心是不再尝试学习正则表达式 - 所以今年为了拯救我免受痛苦,我会向 Stack Overflow 寻求帮助。(去年圣诞混音)。

我想传入一个这样的字符串{getThis},并返回字符串getThis。 有谁可以帮助我遵守我的新年决心吗?


相关问题:


5
这个问题已经被加入到 Stack Overflow 正则表达式 FAQ 中的“高级 Regex-Fu”部分。 - aliteralmind
@Kobi:FAQ是一个维基页面,任何人都可以编辑它。所以去编辑吧。 - aliteralmind
在JS中,一旦我有了来自这里第一个答案的带括号的字符串,我会执行 str.replace('{','').replace('}','').trim() - lost-and-found
17个回答

286

尝试一下

/{(.*?)}/

这意味着匹配 { 和 } 之间的任何字符,但不贪心 - 匹配以 } 结尾的最短字符串(? 阻止 * 贪心)。括号使您可以提取匹配的部分。

另一种方法是

/{([^}]*)}/

这个正则表达式匹配除了 } 字符之外的任何字符(这是另一种非贪婪匹配的方式)。


这很好,但是是否可能在变量数量的花括号组合之间匹配任何内容?例如:"{this should be matched}this shouldnt{this kinda should again}and so {on}"?我想检索不在花括号内的值。另外:花括号不会在句子中使用,也不会有堆叠(这永远不会发生:"{some {text}}"). 有人知道如何做吗?谢谢!(附言:赞成此解决方案) - Igor
5
它没有捕获花括号之间的所有内容,而是捕获花括号内的所有内容以及花括号本身。您如何仅捕获花括号内的内容? 将正则表达式模式修改为仅匹配花括号内部的内容即可。 - Reality-Torrent
1
我喜欢这里不需要转义花括号,因为正则表达式解析器似乎意识到它们不是量词...好吧,我在用Python做这个,但我认为JavaScript的正则表达式也是这样工作的。 - drevicko
3
在末尾添加一个 g,就能进行全局搜索。请查看工作示例 - Benjamin
1
@Reality-Torrent,我也看到了,如果我指定g选项来获取所有匹配项,它会捕获花括号。结果,在JavaScript中,我应该使用Regex.exec循环而不是string.match,同时具有g标志并允许捕获组。请参见https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/match。 - frank
显示剩余3条评论

164
/\{([^}]+)\}/

/        - delimiter
\{       - opening literal brace escaped because it is a special character used for quantifiers eg {2,3}
(        - start capturing
[^}]     - character class consisting of
    ^    - not
    }    - a closing brace (no escaping necessary because special characters in a character class are different)
+        - one or more of the character class
)        - end capturing
\}       - the closing literal brace
/        - delimiter

@meouw sa = s.split("/{([^}]+)}/"); 会产生编译错误。非法重复,无效的转义字符。 - likejudo
@Anil,你似乎正在使用字符串作为你的分割参数而不是正则表达式。你想做什么? - meouw
非常清晰和有用,这一定是得票最多的答案。 - Daniel Rch.

66

如果你的字符串始终保持这种格式,使用正则表达式会过于复杂:

>>> var g='{getThis}';
>>> g.substring(1,g.length-1)
"getThis"
substring(1, g.length-1)的意思是从(紧挨着第一个 {的后面)第一个字符开始,一直取到(但不包括)字符串长度减一的字符。这个方法适用的原因是位置是基于零的,即g.length-1是最后一个位置。
对于除原帖作者之外的读者:如果必须使用正则表达式,如果你想允许空字符串,请使用/{([^}]*)}/;如果你想只匹配花括号之间至少有一个字符的情况,请使用/{([^}]+)}/。其中:
  • /:开始正则表达式模式
    • {:一个字面意义上的花括号
      • (:开始捕获
        • [:开始定义要捕获的字符类
          • ^}:“除了}以外的任何东西”
        • ]:好的,那就是我们整个类定义了
        • *:与我们刚刚定义的类匹配的任意数量的字符
      • ):完成捕获
    • }:紧接着我们捕获的是一个字面意义上的花括号
  • /:结束正则表达式模式

7
截取字符串是一种根据所使用的编程语言而异的操作。在Javascript中,需指定要截取的终止位置;在PHP中,需要指定所需结果的长度(除非长度为负数,这时需要指定要删除的字符数);而在C#中则又不同……令人有些困惑。 - Jerod Venema
2
...而Python只有切片,我认为这比其他任何东西都要好 :p。 - Grant Paul
33
甜美,但不确定它如何成为正则表达式。也许他是在寻求正则表达式的答案,我也来到这里寻求同样的答案...可悲的是答案与问题无关。 - baash05
5
如果你读完整个问题,发帖人甚至都不想学习正则表达式,所以我认为这并不是你所暗示的学术练习。 - Kev
2
我想要做-1,因为问题要求使用正则表达式,我一直在寻找正则表达式,但是被接受的答案对我来说完全没有用(尽管问题本身似乎非常有前途)。在阅读第一个评论后,我必须承认,如果我首先回答这个问题,我可能会以同样/类似的方式回答...所以最终,+1。 - shadyyx
显示剩余11条评论

52

试试这个:

/[^{\}]+(?=})/g

例如

Welcome to RegExr v2.1 by #{gskinner.com},  #{ssd.sd} hosted by Media Temple!

将返回gskinner.comssd.sd


2
很好,你能解释一下为什么在第一个代码块中使用\}吗? - Uzair Ali
3
不错,但这将匹配以}结尾的任何组,即使它不以{开头。 - Ahmad Ibrahim
4
这是唯一正确并且实际可行的答案。 - pldg
3
解释:虽然 [^{}]+ 可以匹配除花括号以外的所有内容,但前瞻断言 (?=}) 只会匹配花括号之前的部分。使用 / ... /g 可以获取所有出现的结果,而不仅仅是第一个。 - 0-_-0
如果你使用ERE,那么你可以这样做:echo 'apple{ _orange_}}}}}{}}\0304\0226{{{}} tree' | mawk '1; gsub("[^}{]+", " | \"&\" | ")^_' :::::::::::: :::::::::::::: ::::::::::: apple{ _orange_}}}}}{}}Ė{{{}} tree ::::::::::::::::::: :::::::::::::: :::::::::::::::::::: : :::::::: | "apple" | { | " _orange_" | }}}}}{}} | "Ė" | {{{}} | " tree" | 确保它只获取除了大括号之外的内容。 - RARE Kpop Manifesto

28

试一试

let path = "/{id}/{name}/{age}";
const paramsPattern = /[^{}]+(?=})/g;
let extractParams = path.match(paramsPattern);
console.log("extractParams", extractParams) // prints all the names between {} = ["id", "name", "age"]

2
这正是我想要的 :) 这将返回没有大括号的结果,其他解决方案会返回带有大括号的结果 - Al-Mothafar
2
非常出色,这里最好的答案。 - michal.jakubeczy

24

这里有一个使用 JavaScript replace 的简单解决方案

var st = '{getThis}';

st = st.replace(/\{|\}/gi,''); // "getThis"

正如上面所接受的答案指出的那样,最初的问题可以使用substring轻松解决,但是使用replace可以解决更复杂的用例。

如果您有一个字符串,例如“randomstring999[fieldname]”,则可以使用稍微不同的模式来获取fieldname。

var nameAttr = "randomstring999[fieldname]";

var justName = nameAttr.replace(/.*\[|\]/gi,''); // "fieldname"

18

这个可以在Textmate中工作,它匹配CSS文件中花括号之间的所有内容。

\{(\s*?.*?)*?\}

选择器 { . . 匹配这里 包括空格 . . }

如果您想进一步能够返回内容,则可以像这样再将其全部包装在一个括号中:

\{((\s*?.*?)*?)\}

你可以通过 $1 访问内容。

对于函数也适用,但我尚未测试嵌套花括号的情况。


17
你想要使用正则表达式的前瞻和后顾来匹配花括号内的内容:
(?<=\{)(.*?)(?=\})

1
上面应该有一个反斜杠转义花括号。它们在我的提交中被剥离了。 - Robert Cesaric
1
这种方法有什么缺点吗? - Somatik
6
@Somatik,是的,ECMAScript不支持负向前瞻和负向后顾。 - RobG
1
注意:此示例适用于Java。返回所有花括号中的值。 - Multiplexor
1
我希望我能够给这个答案更多的赞,因为它是这个页面上唯一正确的答案。 - HisDivineShadow

7
我研究了其他答案,它们似乎缺少一种重要的逻辑。也就是说,选择两个连续括号之间的所有内容,但不包括括号本身。
以下是我的答案:
\{([^{}]+)\}

5

下面的正则表达式可以匹配任何字符,即使在中间有多个闭合大括号:

\{([\s\S]*)\}

示例:

{
  "foo": {
    "bar": 1,
    "baz": 1,
  }
}

救命稻草。正是我所需要的。非常感谢。 - Friedrich Siever

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