正则表达式 - 向前看贪婪但有选择性


Regex - lookahead greedy but optionnal

需要正则表达式的帮助,我花了几个小时在各个方向上尝试,但我似乎无法弄清楚......我有这样的固件文件名:

  • sw_smv-e10200_400_800_6.0.5.2-50o--HF157793_770720_50o_2-prod.sig
  • sw_smv-e10200_400_800_6.0.5.2-50o_761649-prod.sig
  • sw_e10200_400_800_6.0.1.8_146o_60ksso_1-prod.bin.sig
  • sw_smv-e10200_400_800_6.0.1.8_164o_600296-prod.sig

我想提取干净的版本号,例如:

  • 6.0.5.2-50O--HF157793(_50o)_2
  • 6.0.5.2-50o
  • 6.0.1.8_146o_60ksso_1
  • 6.0.1.8_164o

这是我到目前为止的正则表达式:

(e10200_400_800_)(.*)(_[0-9]{6})(.*)?-(prod|stdeb)

但这似乎给我带来了 KSSO 的麻烦,它没有 _[0-9]{6} 匹配,根本无法返回任何内容......如果我添加一个 ?对它,那么我只是排除它,即使在玩懒惰/贪婪时也是如此

(e10200_400_800_)(.*?)(_[0-9]{6})?+(.*?)?-(prod|stdeb)

我也尝试玩前瞻/后视,但无法获得良好的组合......

有人为我提供解决方案吗?

你来了:

([0-9]+'..+?)(?(?=_'d{6})_'d{6}|(_[^_-]+?))(?:_'d{6}|(_.*?))?(?:-prod|-stdeb)

演示。

这令人心碎。条件表达式和替代列表是这里的关键。所需的字符串是所有 3 组的总和。

MATCH 1
1.  [22-43] `6.0.5.2-50o--HF157793`
2.  EMPTY
3.  [50-56] `_50o_2`
MATCH 2
1.  [88-99] `6.0.5.2-50o`
2.  EMPTY
3.  EMPTY
MATCH 3
1.  [138-145]   `6.0.1.8`
2.  [145-150]   `_146o`
3.  [150-159]   `_60ksso_1`
MATCH 4
1.  [195-202]   `6.0.1.8`
2.  [202-207]   `_164o`
3.  EMPTY

这适用于您的示例(?<=_)('d+'.(?:(?!_'d{6}).)+)(?:_'d{6})?(.*)(?=-(?:prod|stdeb))

版本是捕获组 1 与组 2 的 cat。

格式 化:

 (?<= _ )                      # Lookbehind '_'
 (                             # (1 start), Version number  'digit(s) dot plus greedy anything(s)'
      'd+ '.
      (?:
           (?! _ 'd{6} )                 # not '_ 'd{6}' anywhere
           . 
      )+
 )                             # (1 end)
 (?: _ 'd{6} )?                # optional '_666666'
 ( .* )                        # (2), Optional remainder greedy anything(s)
 (?=                           # Lookahead
      -                             # '-'
      (?: prod | stdeb )            # 'prod' or 'stdeb'
 )

输出:

  **  Grp 0 -  ( pos 23 , len 34 ) 
 6.0.5.2-50o--HF157793_770720_50o_2  
  **  Grp 1 -  ( pos 23 , len 21 ) 
 6.0.5.2-50o--HF157793  
  **  Grp 2 -  ( pos 51 , len 6 ) 
 _50o_2  
 --------
  **  Grp 0 -  ( pos 91 , len 18 ) 
 6.0.5.2-50o_761649  
  **  Grp 1 -  ( pos 91 , len 11 ) 
 6.0.5.2-50o  
  **  Grp 2 -  ( pos 109 , len 0 )  EMPTY 
 --------
  **  Grp 0 -  ( pos 139 , len 21 ) 
 6.0.1.8_146o_60ksso_1  
  **  Grp 1 -  ( pos 139 , len 21 ) 
 6.0.1.8_146o_60ksso_1  
  **  Grp 2 -  ( pos 160 , len 0 )  EMPTY 
 --------
  **  Grp 0 -  ( pos 198 , len 19 ) 
 6.0.1.8_164o_600296  
  **  Grp 1 -  ( pos 198 , len 12 ) 
 6.0.1.8_164o  
  **  Grp 2 -  ( pos 217 , len 0 )  EMPTY 

您的文件名称中可以有点(最重要的部分)?如果没有,您可以尝试使用这个

[0-9]'..+(?=-prod|-stdeb)

它适用于您 https://regex101.com/r/hX8eX4/1 给出的示例

似乎有效:

(([0-9]'..+)(?:(?>_'d{6}))(.*)|([0-9]'..+)(?:(?!'d{6})))(?=-prod|-stdeb)

演示在匹配 [2] + [3] 或 [4] 中得到了我想要的结果

谢谢你帮助我!

我认为您正在寻找的工具是一个条件组。

e10200_400_800_'K'd+(?:'.'d+)+[_-]'d+[a-z](?(?!_'d{6}-)[^.]*(?=-prod|-stdeb))

这是条件:

(?(?!_'d{6}-)[^.]*(?=-prod|-stdeb))

如果字符串中的下一项与_'d{6}-不匹配,请继续匹配,直到到达下一项-prod-stdeb的点。 否则,请在此处停止匹配。

演示

我还用了'K,穷人的回望:

e10200_400_800_'K

这允许我匹配e10200_400_800_前缀,以确保匹配从正确的位置开始,但不在匹配中包含前缀。 我本可以使用实际的回溯,但'K更整洁,更灵活。