正则表达式 - 可选字符序列中的捕获组

0 投票
2 回答
36 浏览
提问于 2025-04-12 04:35

我有一个文件,里面有一些我需要从类似JSON的语法中提取的行。我的正则表达式在大多数情况下都能很好地工作,它把我想要的内容提取到第二个捕获组中。但是我注意到,有时候我想要的文本可能会被一些标签包裹起来,而我想忽略这些标签。

示例文件:

    {"title_available" "text1"}
    {"title_value" "<c(20a601)>text2"}
    {"tags"
        {"all" "text3"}
        {"ignore" "text4"}
        {"chargeFactor" "text5 %1%"}
        {"resourceSpeed" "%1% text6"}
    }
    {"rules" "bla-bla-bla\n\n \"BLA\" bla-bla-bla."}
            {"id1" "<c(c3baae)>text7</c>"}

我的正则表达式:

\s+{\"\S+\" \"(<c\(\S+\)>)?(.+)\"}

期望的输出:

text1
text2
text3
text4
text5 %1%
%1% text6
bla-bla-bla\n\n \"BLA\" bla-bla-bla.
text7

当前输出:

all ok except:
text7</c>

我想我需要在第二个捕获组中使用某种前瞻,但我不知道怎么做。另外,我也不确定是否应该为跳过第一个可选的<c...>使用捕获组。有人能帮帮我吗?

附注:模式的速度或简单性并不重要。

2 个回答

2

匹配下面这个正则表达式可以对你所有的例子产生想要的结果。(注意,这里没有使用捕获组。)不过因为你没有说明具体的要求,所以我不确定它对其他字符串是否也适用。

(?:\\\"|[^<>\"])+(?=(?:<[^>]*>)?\"}) 

演示链接

这个表达式可以分解成以下几个部分。

(?:            # begin a non-capture group
  \\\"         # match '\' followed by '"'
|              # or
  [^<>\"]      # match a character other than '<', '>' and '"'
)+             # end non-capture group and execute it >= 1 times
(?=            # begin a positive lookahead
  (?:          # begin a non-capture group
    <          # match '<'
    [^>]*      # match >= 0 characters other than '>'
    >          # match '<'
  )?           # end non-capture group and make it optional
  \"}          # match '"}'
)              # end positive lookahead
2

看起来你的正则表达式没有把结束标签 </c> 从第三个捕获组中排除。要解决这个问题,你可以调整你的正则表达式,让它在有结束标签的情况下把它排除掉。

比如:

\s+{"\S+" "(?:<c\S+>)?(.+?)(?:<\/c>)?"}

撰写回答