有人可以帮助我使用此 javascript 正则表达式将一串列表项转换为仅包含项目文本的数组(没有列表项#或换行符)
Can someone help me with this javascript regex to turn a string of list items into an array with the item texts only (no list item # or new line)
我有两种从 API 返回的字符串。它们看起来如下:
let string1 = "\n1. foo\n2. bar\n3. foobar"
let string2 = "\n\n1. foo.\n\n2. bar.\n\n3. foobar."
明确地说,string 1 总是有 3 个项目返回,string 2 有未知数量的项目返回。但是非常相似的模式。
我想做的是只从每个项目中提取文本到一个数组中。
所以从 string1
我想要 ["foo", "bar", "foobar"]
来自 string2
我想要 ["foo.", "bar.", "foobar."]
我对正则表达式很糟糕,但不知何故,我无意中发现了一个表达式,它可以为两种字符串类型实现这一点,但是,它使用正则表达式的后视,我试图避免这种情况,因为所有浏览器都不支持它:
let regex = /(?<=\. )(.*[a-zA-Z])/g;
let resultArray = str.match(regex);
有人能帮我将这个正则表达式重构为不使用 lookbehind 的东西吗?
编辑:请参阅@Oleg-Barabanov 的解决方案,从技术上讲它要快一些。
string.replace(/\n[0-9.]*/g, "").split(" ").slice(1)
\n
换行
0-9
用于数字(也可以使用 \d
.
为数字后的点
g
替换所有
.split(" ")
在有 space (\s
) 的地方砍掉它
演示:
let string1 = "\n1. foo\n2. bar\n3. foobar"
let string2 = "\n\n1. foo.\n\n2. bar.\n\n3. foobar."
const parse = (str) => str.replace(/\n[0-9.]*/g, "").split(" ").slice(1)
console.log(parse(string1))
console.log(parse(string2))
如果我对你的理解是正确的,那么也许这个解决方案可以帮助你:
const string1 = "\n1. foo\n2. bar\n3. foobar";
const string2 = "\n\n1. foo.\n\n2. bar.\n\n3. foobar.";
const parse = (str) => {
return str.split(/\n[0-9.\s]*/g).filter((item) => item !== "");
}
console.log('Example 1:', parse(string1));
console.log('Example 2:', parse(string2));
OP 的代码使用 String.match
,实际上比建议的解决方案更好。它只需要一个小的调整就可以工作,这就是问题所在:
string1.match(/([A-z].+)/g)
// TEST
[
"\n1. foo\n2. bar\n3. foobar",
"\n\n1. foo.\n\n2. bar.\n\n3. foobar."
].forEach(p => {
console.log( p.match(/([A-z].+)/g) )
});
关于您尝试过的模式 (?<=\. )(.*[a-zA-Z])
的一些注释:
第一部分断言左侧有一个点和 space,但不考虑任何换行符,因此它也可能匹配其他位置
匹配列表项不考虑数字
你的模式的第二部分匹配到字符 A-Za-z 的最后一次出现,它不匹配 string2
示例中的结束点
所有示例字符串都以换行符、数字、点和 1 个或多个 space 开头。
您可以在不使用回顾的情况下获得匹配,并通过以列表项格式开始匹配来使模式更加具体。
然后在捕获组中捕获该行之后的其余部分。
\n\d+\.[^\S\r\n]+(.+)
说明
\n
匹配一个换行符
\d+\.
匹配 1+ 个数字和一个点
[^\S\r\n]+
匹配 1 个或多个 space 没有换行符
(.+)
捕获组 1,匹配 1 个或多个字符
看到一个regex demo.
const regex = /\n\d+\.[^\S\r\n]+(.+)/g;
[
"\n1. foo\n2. bar\n3. foobar",
"\n\n1. foo.\n\n2. bar.\n\n3. foobar."
].forEach(s => {
console.log(Array.from(s.matchAll(regex), m => m[1]))
});
如果字符串也应该在没有前导换行符的情况下匹配,您可以使用锚点 ^
断言字符串的开头并使用多行标志 /m
const regex = /^\d+\.[^\S\r\n]+(.+)/gm;
[
"1. foo\n2. bar\n3. foobar",
"1. foo.\n\n2. bar.\n\n3. foobar."
].forEach(s => {
console.log(Array.from(s.matchAll(regex), m => m[1]))
});
我有两种从 API 返回的字符串。它们看起来如下:
let string1 = "\n1. foo\n2. bar\n3. foobar"
let string2 = "\n\n1. foo.\n\n2. bar.\n\n3. foobar."
明确地说,string 1 总是有 3 个项目返回,string 2 有未知数量的项目返回。但是非常相似的模式。
我想做的是只从每个项目中提取文本到一个数组中。
所以从 string1
我想要 ["foo", "bar", "foobar"]
来自 string2
我想要 ["foo.", "bar.", "foobar."]
我对正则表达式很糟糕,但不知何故,我无意中发现了一个表达式,它可以为两种字符串类型实现这一点,但是,它使用正则表达式的后视,我试图避免这种情况,因为所有浏览器都不支持它:
let regex = /(?<=\. )(.*[a-zA-Z])/g;
let resultArray = str.match(regex);
有人能帮我将这个正则表达式重构为不使用 lookbehind 的东西吗?
编辑:请参阅@Oleg-Barabanov 的解决方案,从技术上讲它要快一些。
string.replace(/\n[0-9.]*/g, "").split(" ").slice(1)
\n
换行0-9
用于数字(也可以使用\d
.
为数字后的点g
替换所有.split(" ")
在有 space (\s
) 的地方砍掉它
演示:
let string1 = "\n1. foo\n2. bar\n3. foobar"
let string2 = "\n\n1. foo.\n\n2. bar.\n\n3. foobar."
const parse = (str) => str.replace(/\n[0-9.]*/g, "").split(" ").slice(1)
console.log(parse(string1))
console.log(parse(string2))
如果我对你的理解是正确的,那么也许这个解决方案可以帮助你:
const string1 = "\n1. foo\n2. bar\n3. foobar";
const string2 = "\n\n1. foo.\n\n2. bar.\n\n3. foobar.";
const parse = (str) => {
return str.split(/\n[0-9.\s]*/g).filter((item) => item !== "");
}
console.log('Example 1:', parse(string1));
console.log('Example 2:', parse(string2));
OP 的代码使用 String.match
,实际上比建议的解决方案更好。它只需要一个小的调整就可以工作,这就是问题所在:
string1.match(/([A-z].+)/g)
// TEST
[
"\n1. foo\n2. bar\n3. foobar",
"\n\n1. foo.\n\n2. bar.\n\n3. foobar."
].forEach(p => {
console.log( p.match(/([A-z].+)/g) )
});
关于您尝试过的模式 (?<=\. )(.*[a-zA-Z])
的一些注释:
第一部分断言左侧有一个点和 space,但不考虑任何换行符,因此它也可能匹配其他位置
匹配列表项不考虑数字
你的模式的第二部分匹配到字符 A-Za-z 的最后一次出现,它不匹配
示例中的结束点string2
所有示例字符串都以换行符、数字、点和 1 个或多个 space 开头。
您可以在不使用回顾的情况下获得匹配,并通过以列表项格式开始匹配来使模式更加具体。
然后在捕获组中捕获该行之后的其余部分。
\n\d+\.[^\S\r\n]+(.+)
说明
\n
匹配一个换行符\d+\.
匹配 1+ 个数字和一个点[^\S\r\n]+
匹配 1 个或多个 space 没有换行符(.+)
捕获组 1,匹配 1 个或多个字符
看到一个regex demo.
const regex = /\n\d+\.[^\S\r\n]+(.+)/g;
[
"\n1. foo\n2. bar\n3. foobar",
"\n\n1. foo.\n\n2. bar.\n\n3. foobar."
].forEach(s => {
console.log(Array.from(s.matchAll(regex), m => m[1]))
});
如果字符串也应该在没有前导换行符的情况下匹配,您可以使用锚点 ^
断言字符串的开头并使用多行标志 /m
const regex = /^\d+\.[^\S\r\n]+(.+)/gm;
[
"1. foo\n2. bar\n3. foobar",
"1. foo.\n\n2. bar.\n\n3. foobar."
].forEach(s => {
console.log(Array.from(s.matchAll(regex), m => m[1]))
});