是否可以使用单个正则表达式查找和提取两个子字符串?

问题描述

花了半天时间阅读SO和其他地方的内容。

说我有一个字符串:

"a_b_c_d_e_f_g_1_2_3_4_5"

是否有一个可以基于两个匹配项构造结果的正则表达式?例如。构造一个由两个匹配项串联而成的字符串:第一个-在第3个和第5个之间,第二个在第8个和第10个下划线之间(不管它们之间还有多少个其他字符)?

以上示例的结果将是:

"d_e_2_3"

谢谢!

解决方法

是否可以使用单个正则表达式查找和提取两个子字符串?

不是,但是可以使用captures groupsString.prototype.replace的正则表达式的组合。

OP用例的正则表达式可能看起来像这样...

(/^(?:[^_]*_){3}([^_]+_[^_]+)_(?:[^_]+_){3}([^_]+_[^_]+).*/)

...并且可以阅读如下...

  1. 有人想从String ... ^的开头开始搜索。
  2. 下一个想要找到不是_ ... [^_]以外的字符序列。
  • 但是由于不能始终确保一个字符串不是以_开头,因此可以选择查找它,因此它变成了[^_]*
  • 当然,这样的序列后面应带有_,因此前一个术语变成[^_]*_
  • 由于该模式本应重复3次({3}),因此需要将其分组((...)),但不应将其捕获(?:)...因此部分表达式变成^(?:[^_]*_){3},并且已经与OP的'a_b_c_'示例中的'a_b_c_d_e_f_g_1_2_3_4_5'相匹配。
  1. 现在,人们希望匹配一个非_字符序列,然后匹配一个_,然后匹配一个非{_字符序列,然后匹配一个_。一个人想要捕获除最后一个_以外的所有内容。因此,正则表达式的第二部分看起来像这样……([^_]+_[^_]+)_
  2. 第三部分与第一部分相似,不同之处在于第三部分肯定存在下一个不是_的字符(序列)。因此,正则表达式的第三部分看起来像这样……(?:[^_]+_){3}
  3. 第四部分是第二部分的确切副本... ([^_]+_[^_]+)
  4. 为了完全匹配该字符串,需要通过一个贪婪的通配推车来替换字符串的其余部分... .匹配任何内容... *,以防仍然有匹配的内容
  5. 由于一个人可能还支持多行匹配,因此必须同时提供全局(g)和多行(m)两个标志。

示例代码...

const regX = (/^(?:[^_]*_){3}([^_]+_[^_]+)_(?:[^_]+_){3}([^_]+_[^_]+).*/gm);


console.log(
  'a_b_c_d_e_f_g_1_2_3_4_5'.replace(regX,'$1_$2')
);
console.log(
  '_b_c_d_e_f_g_1_2_3_4_5'.replace(regX,'$1_$2')
);
console.log(
  'b_c_d_e_f_g_1_2_3_4_5'.replace(regX,'$1_$2')
);
console.log(
  '_c_d_e_f_g_1_2_3_4_5'.replace(regX,'$1_$2')
);


console.log([...
`a_b_c_d_e_f_g_1_2_3_4_5
_b_c_dd_ee_f_g_1_222_333_4_5
b_c_dd_ee_f_g_1_222_333_4_5
_c_dd_ee_ff_g_1_222_333_444_5
c_dd_ee_ff_g_1_222_333_444_55_66
_dd_ee_ff_gg_1_222_333_444_55_66`
.matchAll(regX)].map(([match,$1,$2]) => ($1 + '_' + $2))
);
.as-console-wrapper { min-height: 100%!important; top: 0; }

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...