使用正则表达式根据标签和文本拆分字符串



我需要解析一个字符串,它包含文本内容和特定的标记。

预期结果必须是一个包含条目的数组,文本和标签之间有分隔。

要解析的字符串示例

There is user [[user-foo]][[/user-foo]] and user [[user-bar]]label[[/user-bar]].

一些信息:

  • user-标签是静态的
  • foobar是动态的,可以是任意字符串。
  • 文本部分相同。
  • 标签可以接收一些子文本。

预期结果
[
'There is user ',
'[[user-foo]][[/user-foo]]',
' and user ',
'[[user-bar]]label[[/user-bar]]',
'.'
]

What I tried

下面是我创建的正则表达式:

/[[user-[^]]+]][A-Za-z]*[[/user-[^]]+]]/g

在此可见/可编辑:https://regex101.com/r/ufwVV1/1

它标识所有标记部分,并返回与我拥有的两个标记相关的两个匹配项。但是,文本内容不包括在内。我不知道第一种方法是否正确。

也许在效率方面有更好的解决方案…但至少,这是可行的。

  1. 使用regex
  2. 获取标签
  3. 获取标签在字符串
  4. 中的位置(开始/结束)
  5. 对字符串
  6. 使用这些位置

const string = "There is user [[user-foo]][[/user-foo]] and user [[user-bar]]label[[/user-bar]]."
// Get the tags using regex
const matches = string.match(/[[[a-z-/]+]]/g)
console.log(matches)
// Get the tags position (start/end) within the string
const matchPositions = matches.map((match) => ({start: string.indexOf(match), end: string.indexOf(match) + match.length}))
console.log(matchPositions)
// Use those positions against the string
let currentPos = 0
let result = []
for(let i=0; i<matchPositions.length; i+=2){
const position = matchPositions[i]
const secondPosition  = matchPositions[i+1]

// Get the substring in front of the current tag (if any)
if(position.start !== currentPos){
const firstSubString = string.slice(currentPos, position.start)
if(firstSubString !== ""){
result.push(firstSubString)
}
}

// Get the substring from the opening tag start to the closing tag end
result.push(string.slice(position.start, secondPosition.end))
currentPos = secondPosition.end

// Get the substring at the end of the string (if any)
if(i === matchPositions.length-2){
const lastSubString = string.slice(secondPosition.end)
if(lastSubString !== ""){
result.push(lastSubString)
}

}
}
console.log(result)

这是我的解决方案,灵感来自@louys-patrice-bessette的回答。

const string = 'There is user [[user-foo]][[/user-foo]] and user [[user-bar]]label[[/user-bar]].';
const regex = /[[user-[^]]+]][A-Za-z0-9_ ]*[[/user-[^]]+]]/g;
const { index, items } = [...string.matchAll(regex)].reduce(
(result, regExpMatchArray) => {
const [match] = regExpMatchArray;
const { index: currentIndex } = regExpMatchArray;
if (currentIndex === undefined) {
return result;
}
return {
items: [
...result.items,
string.substring(result.index, currentIndex),
match,
],
index: currentIndex + match.length,
};
},
{
index: 0,
items: [],
}
);
if (index !== string.length) {
items.push(string.substring(index, string.length));
}
console.log(items);

最新更新