复杂的字符串拆分
Complicated split of string
我有一组结构相似的字符串,我试图通过 JavaScript 将它们分解成单独的部分。
示例字符串:
Jr. Kevin Hooks, Irene Cara, Moses Gunn, Robert Hooks, Ernestine Jackson, José Feliciano. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur ullamcorper sodales nulla id hendrerit.
理想输出:
[
"Jr. Kevin Hooks","Irene Cara",…
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur
ullamcorper sodales nulla id hendrerit."
]
我的第一个想法是在 '. ' 将名称从文本块中分离到最后,然后在 ', ' 处拆分名称组,但是因为有些名称像 'Jr. Kevin Hooks' 并且文本块也包含 '. ' 这种方法失败了。使用 ', ' 作为键也会失败,因为文本块包含 ', '.
关于如何完成此任务有什么建议吗?
非常感谢!
如果我们可以假设:
- 名字出现之前没有文字
- 名称中的点仅出现在最多 3 个字母的单词的末尾
- 如果最后出现的名字以这样的缩写结尾,那么它后面还需要跟一个点来结束列表(例如"Abram Lincoln, John Johnsen Jr.. Lorem ipsum dolor"),否则无法知道下一个是否出现单词是否属于名称。
那么你可以使用这个正则表达式:
/([a-z]{1,3}\.|[^\s,.]+)(\s+([a-z]{1,3}\.|[^\s,.]+))*(?=[,.])|\..*$/ig
var text = 'Jr. Kevin Hooks, Irene Cara, Moses Gunn, Robert Hooks, Ernestine Jackson, José Feliciano. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur ullamcorper sodales nulla id hendrerit.'
var result = text.match(/([a-z]{1,3}\.|[^\s,.]+)(\s+([a-z]{1,3}\.|[^\s,.]+))*(?=[,.])|\..*$/ig);
// Optionally remove the point at the start of the last match:
if (result) result.push(result.pop().replace(/^\.\s*/, ''));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
解释:
[a-z]{1,3}\.
匹配一到三个拉丁字符,后跟一个点
[^\s,.]+)
匹配非白色-space、逗号或点 的一对多字符
( | )
: either must match: 以上两种模式以这种方式组合,意味着名称中的单词必须最多三个拉丁字母后跟一个点,或者任意数量的非白色-space,不包括逗号和点。
(\s+([a-z]{1,3}\.|[^\s,.]+))*
:可选(*
)允许更多这样的词:匹配一个或多个白色 spaces,并重复开头的模式。
(?=[,.])
那一系列的单词必须以逗号或点结尾,不抓取(只能向前看):通过不抓取点,我们肯定知道开头的模式不能不再匹配,那就是下一个模式将完成工作的时间:
\..*$
匹配文字点,然后匹配字符串末尾的任何字符 ($
)
最后一个文本块之前的点也包含在最后一个匹配项中,因此您可能希望单独删除它(参见代码段)。
我有一组结构相似的字符串,我试图通过 JavaScript 将它们分解成单独的部分。
示例字符串:
Jr. Kevin Hooks, Irene Cara, Moses Gunn, Robert Hooks, Ernestine Jackson, José Feliciano. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur ullamcorper sodales nulla id hendrerit.
理想输出:
[
"Jr. Kevin Hooks","Irene Cara",…
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur
ullamcorper sodales nulla id hendrerit."
]
我的第一个想法是在 '. ' 将名称从文本块中分离到最后,然后在 ', ' 处拆分名称组,但是因为有些名称像 'Jr. Kevin Hooks' 并且文本块也包含 '. ' 这种方法失败了。使用 ', ' 作为键也会失败,因为文本块包含 ', '.
关于如何完成此任务有什么建议吗?
非常感谢!
如果我们可以假设:
- 名字出现之前没有文字
- 名称中的点仅出现在最多 3 个字母的单词的末尾
- 如果最后出现的名字以这样的缩写结尾,那么它后面还需要跟一个点来结束列表(例如"Abram Lincoln, John Johnsen Jr.. Lorem ipsum dolor"),否则无法知道下一个是否出现单词是否属于名称。
那么你可以使用这个正则表达式:
/([a-z]{1,3}\.|[^\s,.]+)(\s+([a-z]{1,3}\.|[^\s,.]+))*(?=[,.])|\..*$/ig
var text = 'Jr. Kevin Hooks, Irene Cara, Moses Gunn, Robert Hooks, Ernestine Jackson, José Feliciano. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur ullamcorper sodales nulla id hendrerit.'
var result = text.match(/([a-z]{1,3}\.|[^\s,.]+)(\s+([a-z]{1,3}\.|[^\s,.]+))*(?=[,.])|\..*$/ig);
// Optionally remove the point at the start of the last match:
if (result) result.push(result.pop().replace(/^\.\s*/, ''));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
解释:
[a-z]{1,3}\.
匹配一到三个拉丁字符,后跟一个点[^\s,.]+)
匹配非白色-space、逗号或点 的一对多字符
( | )
: either must match: 以上两种模式以这种方式组合,意味着名称中的单词必须最多三个拉丁字母后跟一个点,或者任意数量的非白色-space,不包括逗号和点。(\s+([a-z]{1,3}\.|[^\s,.]+))*
:可选(*
)允许更多这样的词:匹配一个或多个白色 spaces,并重复开头的模式。(?=[,.])
那一系列的单词必须以逗号或点结尾,不抓取(只能向前看):通过不抓取点,我们肯定知道开头的模式不能不再匹配,那就是下一个模式将完成工作的时间:\..*$
匹配文字点,然后匹配字符串末尾的任何字符 ($
)
最后一个文本块之前的点也包含在最后一个匹配项中,因此您可能希望单独删除它(参见代码段)。