如何在 JavaScript 中标记整个正则表达式?
How can I tokenize entire regex in JavaScript?
我正在尝试解析时间字符串并将它们转码为我要调用的对象 time module
。它只是一个简单的字典对象,具有完整的时间披露。
问题是我必须匹配由数字和时间单位组成的字符串。目前我正在尝试匹配这个正则表达式:
/^(([1-9][0-9]*)(y|m|w|d|h|min|s))+$/g
.
我需要它来产生每一场比赛。所以如果我给它输入这个字符串:12y12m12w12d12h12min12s
- 它应该 return 像这样的数组:
[
'12y12m12w12d12h12min12s', // Matching string
'12y',
'12',
'y',
'12m',
'12',
'm',
'12w',
'12',
'w',
'12d',
'12',
'd',
'12h',
'12',
'h',
'12min',
'12',
'min',
'12s',
'12',
's',
index: 0,
input: '12y12m12w12d12h12min12s',
groups: undefined
]
相反,它 return 只是最后一个单元:
[
'12y12m12w12d12h12min12s',
'12s',
'12',
's',
index: 0,
input: '12y12m12w12d12h12min12s',
groups: undefined
]
我可以使用 regex
来做这件事吗?怎么样?
您不应尝试一次匹配整个输入,因为带有 +
后缀的捕获组确实只会捕获最后一个匹配项。
而是迭代子匹配项。如果你需要整个字符串最终匹配,没有任何中断的字符序列,那么调整你的正则表达式,以便它也匹配单独捕获组中的偏离字符:
let regex = /([1-9][0-9]*)(y|min|m|w|d|h|s)|(.)/g
let s = "12y12m12w12d12h12min12s";
let matches = [...s.matchAll(regex)];
console.log(matches);
因此,输出是一个二维数组,其中每行有 4 个元素:
- 一个时间单位的完全匹配
- 数字部分
- 单元部分
- 如果这不是
undefined
,则此行表示与数字单位模式不匹配的字符
请注意,我在您的正则表达式中将 min
移到了 m
之前,因为您希望 min
匹配优先于简单的 m
匹配。
您可以过滤该数组以查看是否存在与第 4 个值不匹配的项。如果没有,数组可以很容易地简化为您的示例输出。
let regex = /([1-9][0-9]*)(y|min|m|w|d|h|s)|(.)/g
let s = "12y12m12w12d12h12min12s";
let matches = [...s.matchAll(regex)];
if (matches.some(row => row[3])) throw "not matching completely";
matches = matches.flatMap(row => row.slice(0,3));
console.log(matches);
捕获组仅捕获 最后 场比赛。
新的 matchAll
method 将在 ES2020 中发布(并且很容易填充),如果您移除锚点并展平结果,您会非常接近:
const rex = /([1-9][0-9]*)(y|min|m|w|d|h|s)/g;
const str = "12y12m12w12d12h12min12s";
const array = [...str.matchAll(rex)].flat();
console.log(array);
这不会为您提供整体的整个字符串匹配(如果需要,插入数组中),但它会为您提供所有其余部分:
实例:
const rex = /([1-9][0-9]*)(y|min|m|w|d|h|s)/g;
const str = "12y12m12w12d12h12min12s";
const array = [...str.matchAll(rex)].flat();
console.log(array);
.as-console-wrapper {
max-height: 100% !important;
}
如果你不想使用matchAll
,你需要一个循环:
const result = [];
let match;
while ((match = rex.exec(str)) !== null) {
result.push(...match);
}
实例:
const rex = /([1-9][0-9]*)(y|min|m|w|d|h|s)/g;
const str = "12y12m12w12d12h12min12s";
const result = [];
let match;
while ((match = rex.exec(str)) !== null) {
result.push(...match);
}
console.log(result);
.as-console-wrapper {
max-height: 100% !important;
}
我正在尝试解析时间字符串并将它们转码为我要调用的对象 time module
。它只是一个简单的字典对象,具有完整的时间披露。
问题是我必须匹配由数字和时间单位组成的字符串。目前我正在尝试匹配这个正则表达式:
/^(([1-9][0-9]*)(y|m|w|d|h|min|s))+$/g
.
我需要它来产生每一场比赛。所以如果我给它输入这个字符串:12y12m12w12d12h12min12s
- 它应该 return 像这样的数组:
[
'12y12m12w12d12h12min12s', // Matching string
'12y',
'12',
'y',
'12m',
'12',
'm',
'12w',
'12',
'w',
'12d',
'12',
'd',
'12h',
'12',
'h',
'12min',
'12',
'min',
'12s',
'12',
's',
index: 0,
input: '12y12m12w12d12h12min12s',
groups: undefined
]
相反,它 return 只是最后一个单元:
[
'12y12m12w12d12h12min12s',
'12s',
'12',
's',
index: 0,
input: '12y12m12w12d12h12min12s',
groups: undefined
]
我可以使用 regex
来做这件事吗?怎么样?
您不应尝试一次匹配整个输入,因为带有 +
后缀的捕获组确实只会捕获最后一个匹配项。
而是迭代子匹配项。如果你需要整个字符串最终匹配,没有任何中断的字符序列,那么调整你的正则表达式,以便它也匹配单独捕获组中的偏离字符:
let regex = /([1-9][0-9]*)(y|min|m|w|d|h|s)|(.)/g
let s = "12y12m12w12d12h12min12s";
let matches = [...s.matchAll(regex)];
console.log(matches);
因此,输出是一个二维数组,其中每行有 4 个元素:
- 一个时间单位的完全匹配
- 数字部分
- 单元部分
- 如果这不是
undefined
,则此行表示与数字单位模式不匹配的字符
请注意,我在您的正则表达式中将 min
移到了 m
之前,因为您希望 min
匹配优先于简单的 m
匹配。
您可以过滤该数组以查看是否存在与第 4 个值不匹配的项。如果没有,数组可以很容易地简化为您的示例输出。
let regex = /([1-9][0-9]*)(y|min|m|w|d|h|s)|(.)/g
let s = "12y12m12w12d12h12min12s";
let matches = [...s.matchAll(regex)];
if (matches.some(row => row[3])) throw "not matching completely";
matches = matches.flatMap(row => row.slice(0,3));
console.log(matches);
捕获组仅捕获 最后 场比赛。
新的 matchAll
method 将在 ES2020 中发布(并且很容易填充),如果您移除锚点并展平结果,您会非常接近:
const rex = /([1-9][0-9]*)(y|min|m|w|d|h|s)/g;
const str = "12y12m12w12d12h12min12s";
const array = [...str.matchAll(rex)].flat();
console.log(array);
这不会为您提供整体的整个字符串匹配(如果需要,插入数组中),但它会为您提供所有其余部分:
实例:
const rex = /([1-9][0-9]*)(y|min|m|w|d|h|s)/g;
const str = "12y12m12w12d12h12min12s";
const array = [...str.matchAll(rex)].flat();
console.log(array);
.as-console-wrapper {
max-height: 100% !important;
}
如果你不想使用matchAll
,你需要一个循环:
const result = [];
let match;
while ((match = rex.exec(str)) !== null) {
result.push(...match);
}
实例:
const rex = /([1-9][0-9]*)(y|min|m|w|d|h|s)/g;
const str = "12y12m12w12d12h12min12s";
const result = [];
let match;
while ((match = rex.exec(str)) !== null) {
result.push(...match);
}
console.log(result);
.as-console-wrapper {
max-height: 100% !important;
}