如何在Regex中使用非捕获组跳过文本中的中间字符

gajydyqb  于 2023-08-08  发布在  其他
关注(0)|答案(3)|浏览(83)

我有下面的示例文本:
1000031231
我需要捕获一个值为:131231,也就是说,它应该忽略第一个非零数字和之后的其他非零数字之间的零。
有什么办法吗?
尝试:
([123456789]?(?:0*)[123456789]*)
但捕获的组返回完整的原始字符串1000031231。
预期:
131231

slwdgvem

slwdgvem1#

如果已知(如示例中所示)字符串中的所有零都被分组在一起(彼此相邻),则只需将每个零替换为空字符串。我假设可能有不止一组零。
这里有几种方法可以做到这一点。但是,没有一个使用非捕获组。
您可以尝试匹配正则表达式

^([1-9]*)0*(.*)

字符串
如果有匹配项,则所需的字符串将是$1+$2(在不同的语言中可能会有不同的写法。
Demo
将光标悬停在链接处正则表达式的每个部分上,以获得其功能的说明。
如果正则表达式引擎支持\K(将报告的匹配的起始点重置为当前字符串位置,并丢弃任何以前使用的字符),则可以将以下正则表达式匹配的字符转换为空字符串。

^[1-9]*\K0*


Demo
正则表达式引擎支持\K的语言包括PHP、perl、Ruby、R(带有perl=TRUE)和Python(带有PyPI模块)。
如果你使用的语言支持可变长度的lookbehind,比如C++和JavaScript,你可以用空字符串替换下面正则表达式的匹配项。

(?<=^[1-9]*)0*


Demo

wfauudbj

wfauudbj2#

从输入字符串中删除所有零的最简单方法是简单地 * 删除 * 它们:

/0+/g  // replace this match with ""

字符串
在JavaScript中,这可以通过String.replace()来完成:

const test=`10000312000031
1100003100023000100008
000031231
100000000`.split("\n");

test.forEach(t=>console.log(t.replace(/0+/g,"")))

jyztefdp

jyztefdp3#

不能在连续匹配中跳过字符,因此不能在单个组匹配中获取多个分隔的组值。
它应该忽略第一个非零数字和其后的其他非零数字之间的零。
这里没有提到语言,但是如果没有全局匹配,您可以使用单个捕获组来保留数字1-9,然后匹配1次或多次0,并在右侧Assert数字1-9。

([1-9])0+(?=[1-9])

字符串
Regex demo

const strings = [
  "1000031231",
  "100031001",
  "001000031231",
  "0100031001",
  "012300031001"
];
const regex = /([1-9])0+(?=[1-9])/;
strings.forEach(s => {
  const result = s.replace(regex, "$1")
  console.log(`${s} --> ${result}`);
});


或者,如果你想替换多个示例,你可以使用一个锚点^来Assert字符串的开头,后面跟着可选的零,然后你也可以在组1中保留这些零,如果你不能使用lookarounds,你也可以捕获组2中的最后一个数字1-9,并在替换中使用这两个组:

^(0*[1-9]+)0+([1-9])


Regex demo

const strings = [
  "1000031231",
  "100031001",
  "001000031231",
  "0100031001",
  "012300031001"
];
const regex = /^(0*[1-9]+)0+([1-9])/g;
strings.forEach(s => {
  const result = s.replace(regex, "$1$2")
  console.log(`${s} --> ${result}`);
});

相关问题