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

Regular Expression - Match End if Start is Match

我要匹配以下字符串:

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

我可以只使用一个正则表达式来实现吗?

我目前正在使用这个 '^\[({)?.+(})?]$',但它也会匹配:

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

只有在使用 { 时,我才需要匹配 }

请注意,我只能使用正则表达式匹配函数,因为我已将其实现为 SQL CLR 函数,以便在 T-SQL 语句中使用它。

您的正则表达式 ^\[({)?.+(})?]$ 将仅匹配单个字符串,例如 [{...}][{...],因为 1) 您有锚点 (^$),并且两个大括号都存在同样的模式。

我建议使用负向后视来避免匹配 []-ed 字符串中只有 1 个大括号的字符串,如下所示:

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();

这将确保您匹配 []-ed 字符串,即使在更大的上下文中也是如此。

结果:

我成功了:\[[^{].*[^}]\]|\[\{.*\}\]

编辑 正如 OP 指出的那样,括号之间需要一些东西,所以 'one or more' 匹配更合适:

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

see RegEx example here

基本上你可以这样写(逐字串):

^\[(?:{.+}|[^]{}]+)]$

你可以使用更复杂的条件语句 (?(condition)then|else):

^\[({)?[^]{}]+(?(1)}|)]$

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

但这种方式效率可能较低

试试这个:

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

分解后匹配 3 种类型的字符串:

  1. [] 周围 ≥ 2 个字符,前提是第一个字符不是 { 并且最后一个字符不是 }
  2. [{}] 周围任何东西
  3. [] 围绕单个非花括号字符(以前的答案未涵盖的边缘情况)

好的,我知道这个问题已经得到解答,但我想我会展示一个纯 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