正则表达式-如果开始匹配,则匹配结尾

5

我想匹配以下字符串:

[anything can be here]
[{anything can be here}]

我能否只使用一个正则表达式来实现这个功能?

我目前正在使用这个正则表达式'^\[({)?.+(})?]$',但它也会匹配以下内容:

[anything can be here}]
[{anything can be here]

我需要匹配},但只有在使用{时才能匹配。
请注意,我只能使用正则表达式匹配函数,因为我已将其实现为SQL CLR函数,以便在T-SQL语句中使用。
5个回答

4
基本上,您可以编写(verbatim字符串):
^\[(?:{.+}|[^]{}]+)]$

您可以使用条件语句 (?(condition)then|else) 来实现更复杂的功能:
^\[({)?[^]{}]+(?(1)}|)]$

(如果捕获组1存在,则},否则为空)

但这种方式可能不太高效。


1
在条件语句中,甚至不需要使用 |,只需使用 ^\[({)?[^]{}]+(?(1)})]$ 就足够了(仅包含 yes 部分)。 - Wiktor Stribiżew
@stribizhev:确实,这只是为了说明条件结构。但正如我所说,使用这种方式是过度的,仅供参考。 - Casimir et Hippolyte

2
你的正则表达式^\[({)?.+(})?]$只会匹配像[{...}][{...]这样的单个字符串,因为你有锚点(^$),并且两个花括号同时存在于同一个模式中。
我建议使用负向回顾来避免匹配像这样只有一个花括号的字符串:[]中包含的字符串。
var rgx = new Regex(@"((?!\[\{[^}]+\]|\[[^{]+\})\[\{?.+?\}?\])");
var tst = "[anything can be here] [{anything can be here}] [anything can be here}] [{anything can be here]";
var mtch = rgx.Matches(tst).Cast<Match>().ToList();

这将确保在更大的上下文中也能匹配带有[]的字符串。
结果:

输入图像说明


2
我搞定了:\[[^{].*[^}]\]|\[\{.*\}\] 编辑 正如被提出的,需要在括号中放入一些内容,以便更适合“一个或多个”匹配: \[[^{].+[^}]\]|\[\{.+\}\] 在这里查看RegEx示例

1

试试这个:

\[[^{].*[^}]\]|\[[^{}]\]|\[\{.+\}\]

这段文字可以分为三种类型的字符串:

  1. [] 包围着至少两个字符,但首字符不是 { 且末字符不是 }
  2. [{}] 包围着任何内容
  3. [] 包围着单个非花括号字符(前面的回答未涵盖此特殊情况)

我认为它的工作不太恰当。它 1) 太贪心了,2) 匹配了不需要的情况。请参见 http://goo.gl/9dlTyX - Wiktor Stribiżew

0

好的,我知道这个问题已经有答案了,但是我想展示一个纯T-SQL解决方案,作为另一种选择。

DECLARE @yourTable TABLE (val VARCHAR(100));
INSERT INTO @yourTable
    VALUES  ('[anything can be here]'),
            ('[{anything can be here}]'),
            ('[anything can be here}]'),
            ('[{anything can be here]');

WITH CTE_Brackets
AS
(
    SELECT  val,
            CASE 
                WHEN CHARINDEX('{',val) > 0 THEN CHARINDEX('{',val)
            END  AS L_curly,
            CASE 
                WHEN CHARINDEX('}',val) > 0 THEN CHARINDEX('}',val)
            END AS R_curly,

            CASE 
                WHEN CHARINDEX('[',val) > 0 THEN CHARINDEX('[',val)
            END  AS L_bracket,
            CASE 
                WHEN CHARINDEX(']',val) > 0 THEN CHARINDEX(']',val)
            END  AS R_bracket
    FROM @yourTable
),
CTE_string
AS
(
    SELECT  val,
            L_curly,
            R_curly,
            L_bracket,
            R_bracket,
            SUBSTRING(val,start_pos,end_pos - start_pos) val_string
    FROM CTE_Brackets A
    CROSS APPLY (SELECT COALESCE(L_curly,L_bracket) + 1 AS start_pos,
                        COALESCE(R_curly,R_bracket)     AS end_pos
                ) CA
)

SELECT A.val,B.val
FROM CTE_string A
INNER JOIN CTE_string B
    ON A.val_string = B.val_string
    AND
    (
        (
                    A.L_curly IS NOT NULL
                AND A.R_curly IS NULL
                AND B.L_curly IS NULL
                AND B.R_curly IS NOT NULL
        ) --left curly matching right only curly
        OR 
        (
                    A.L_curly + A.R_curly IS NOT NULL
                AND B.R_curly IS NULL
                AND B.L_curly IS NULL
        ) --matches both curly to no curly
    )
ORDER BY B.val

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