字符串操作 JavaScript - 替换占位符
String manipulation JavaScript - replace placeholders
我有一个很长的字符串,我必须以特定的方式对其进行操作。该字符串可以包含其他子字符串,这会导致我的代码出现问题。出于这个原因,在对字符串做任何事情之前,我用格式:[=15=]
、</code>、<code>
、...、$n
。我确定主字符串本身不包含字符 $
但子字符串之一(或更多)可能是例如 "[=20=]"
.
现在的问题是:在 manipulation/formatting 主字符串之后,我需要再次用它们的实际值替换所有占位符。
为了方便,我将它们保存为这种格式:
// TypeScript
let substrings: { placeholderName: string; value: string }[];
但是在做:
// JavaScript
let mainString1 = "main string [=12=] ";
let mainString2 = "main string [=12=] ";
let substrings = [
{ placeholderName: "[=12=]", value: "test1 " },
{ placeholderName: "", value: "test2" }
];
for (const substr of substrings) {
mainString1 = mainString1.replace(substr.placeholderName, substr.value);
mainString2 = mainString2.replaceAll(substr.placeholderName, substr.value);
}
console.log(mainString1); // expected result: "main string test1 test2 "
console.log(mainString2); // expected result: "main string test1 test2 test2"
// wanted result: "main string test1 test2"
不是一个选项,因为子字符串可能包括$x
,这会替换错误的东西(通过.replace()
和 .replaceAll()
).
获取子字符串是用正则表达式存档的,也许正则表达式也能帮上忙?虽然我无法控制子字符串中保存的内容...
这可能不是最有效的代码。但这是我用评论制作的功能。
注意:请小心,因为如果将相同的占位符放在其自身内部,则会产生无限循环。例如:
{ placeholderName: "", value: "test2 " }
let mainString1 = "main string [=11=] ";
let mainString2 = "main string [=11=] ";
let substrings = [{
placeholderName: "[=11=]",
value: "test1 "
},
{
placeholderName: "",
value: "test2"
},
];
function replacePlaceHolders(mainString, substrings) {
let replacedString = mainString
//We will find every placeHolder, the followin line wil return and array with all of them. Ex: ['', $n']
let placeholders = replacedString.match(/$[0-9]*/gm)
//while there is some place holder to replace
while (placeholders !== null && placeholders.length > 0) {
//We will iterate for each placeholder
placeholders.forEach(placeholder => {
//extrac the value to replace
let value = substrings.filter(x => x.placeholderName === placeholder)[0].value
//replace it
replacedString = replacedString.replace(placeholder, value)
})
//and finally see if there is any new placeHolder inserted in the replace. If there is something the loop will start again.
placeholders = replacedString.match(/$[0-9]*/gm)
}
return replacedString
}
console.log(replacePlaceHolders(mainString1, substrings))
console.log(replacePlaceHolders(mainString2, substrings))
编辑:
好的...我想我现在明白了您的问题...您不想替换值中的 placeHoldersLike 字符串。
此版本的代码应按预期工作,您不必担心这里的无限循环。但是,请注意您的占位符,“$”是正则表达式中的保留字符,它们更多是您应该转义的。我假设您所有的占位符都将像“$1”、“$2”等。如果不是,您应该编辑 regexPlaceholder 函数来包装和转义该字符。
let mainString1 = "main string [=12=] ";
let mainString2 = "main string [=12=] ";
let substrings = [
{ placeholderName: "[=12=]", value: " test1 " },
{ placeholderName: "", value: "test2 " },
{ placeholderName: "", value: "test3" },
];
function replacePlaceHolders(mainString, substrings) {
//You will need to escape the $ characters or maybe even others depending of how you made your placeholders
function regexPlaceholder(p) {
return new RegExp('\' + p, "gm")
}
let replacedString = mainString
//We will find every placeHolder, the followin line wil return and array with all of them. Ex: ['', $n']
let placeholders = replacedString.match(/$[0-9]*/gm)
//if there is any placeHolder to replace
if (placeholders !== null && placeholders.length > 0) {
//we will declare some variable to check if the values had something inside that can be
//mistaken for a placeHolder.
//We will store how many of them have we changed and replace them back at the end
let replacedplaceholdersInValues = []
let indexofReplacedValue = 0
placeholders.forEach(placeholder => {
//extrac the value to replace
let value = substrings.filter(x => x.placeholderName === placeholder)[0].value
//find if the value had a posible placeholder inside
let placeholdersInValues = value.match(/$[0-9]*/gm)
if (placeholdersInValues !== null && placeholdersInValues.length > 0) {
placeholdersInValues.forEach(placeholdersInValue => {
//if there are, we will replace them with another mark, so our primary function wont change them
value = value.replace(regexPlaceholder(placeholdersInValue), "<markToReplace" + indexofReplacedValue + ">")
//and store every change to make a rollback later
replacedplaceholdersInValues.push({
placeholderName: placeholdersInValue,
value: "<markToReplace" + indexofReplacedValue + ">"
})
})
indexofReplacedValue++
}
//replace the actual placeholders
replacedString = replacedString.replace(regexPlaceholder(placeholder), value)
})
//if there was some placeholderlike inside the values, we change them back to normal
if (replacedplaceholdersInValues.length > 0) {
replacedplaceholdersInValues.forEach(replaced => {
replacedString = replacedString.replace(replaced.value, replaced.placeholderName)
})
}
}
return replacedString
}
console.log(replacePlaceHolders(mainString1, substrings))
console.log(replacePlaceHolders(mainString2, substrings))
关键是选择一个占位符,在主串和子串中都不可能。我的技巧是使用 non-printable 个字符作为占位符。我最喜欢的是 NUL
字符 (0x00
),因为大多数其他人不会使用它,因为 C/C++ 认为它是字符串的结尾。 Javascript 然而足够强大以处理包含 NUL 的字符串(编码为 unicode \0000):
let mainString1 = "main string [=10=]-0 [=10=]-1";
let mainString2 = "main string [=10=]-0 [=10=]-1";
let substrings = [
{ placeholderName: "[=10=]-0", value: "test1 " },
{ placeholderName: "[=10=]-1", value: "test2" }
];
其余代码无需更改。
请注意,我使用 -
字符来防止 javascript 将您的数字 0
和 1
解释为八进制 [=16=]
的一部分.
如果您像大多数程序员一样厌恶 [=16=]
,那么您可以使用任何其他 non-printing 字符,例如 </code>(标题开始)、<code>007
(使您的终端发出铃声的角色 - 还有 James Bond) 等
如果您确定所有占位符都将遵循 $x
格式,我会使用带有回调的 .replace()
方法:
const result = mainString1.replace(
/$\d+/g,
placeholder => substrings.find(
substring => substring.placeholderName === placeholder
)?.value ?? placeholder
);
// result is "main string test1 test2"
我有一个很长的字符串,我必须以特定的方式对其进行操作。该字符串可以包含其他子字符串,这会导致我的代码出现问题。出于这个原因,在对字符串做任何事情之前,我用格式:[=15=]
、</code>、<code>
、...、$n
。我确定主字符串本身不包含字符 $
但子字符串之一(或更多)可能是例如 "[=20=]"
.
现在的问题是:在 manipulation/formatting 主字符串之后,我需要再次用它们的实际值替换所有占位符。
为了方便,我将它们保存为这种格式:
// TypeScript
let substrings: { placeholderName: string; value: string }[];
但是在做:
// JavaScript
let mainString1 = "main string [=12=] ";
let mainString2 = "main string [=12=] ";
let substrings = [
{ placeholderName: "[=12=]", value: "test1 " },
{ placeholderName: "", value: "test2" }
];
for (const substr of substrings) {
mainString1 = mainString1.replace(substr.placeholderName, substr.value);
mainString2 = mainString2.replaceAll(substr.placeholderName, substr.value);
}
console.log(mainString1); // expected result: "main string test1 test2 "
console.log(mainString2); // expected result: "main string test1 test2 test2"
// wanted result: "main string test1 test2"
不是一个选项,因为子字符串可能包括$x
,这会替换错误的东西(通过.replace()
和 .replaceAll()
).
获取子字符串是用正则表达式存档的,也许正则表达式也能帮上忙?虽然我无法控制子字符串中保存的内容...
这可能不是最有效的代码。但这是我用评论制作的功能。
注意:请小心,因为如果将相同的占位符放在其自身内部,则会产生无限循环。例如:
{ placeholderName: "", value: "test2 " }
let mainString1 = "main string [=11=] ";
let mainString2 = "main string [=11=] ";
let substrings = [{
placeholderName: "[=11=]",
value: "test1 "
},
{
placeholderName: "",
value: "test2"
},
];
function replacePlaceHolders(mainString, substrings) {
let replacedString = mainString
//We will find every placeHolder, the followin line wil return and array with all of them. Ex: ['', $n']
let placeholders = replacedString.match(/$[0-9]*/gm)
//while there is some place holder to replace
while (placeholders !== null && placeholders.length > 0) {
//We will iterate for each placeholder
placeholders.forEach(placeholder => {
//extrac the value to replace
let value = substrings.filter(x => x.placeholderName === placeholder)[0].value
//replace it
replacedString = replacedString.replace(placeholder, value)
})
//and finally see if there is any new placeHolder inserted in the replace. If there is something the loop will start again.
placeholders = replacedString.match(/$[0-9]*/gm)
}
return replacedString
}
console.log(replacePlaceHolders(mainString1, substrings))
console.log(replacePlaceHolders(mainString2, substrings))
编辑:
好的...我想我现在明白了您的问题...您不想替换值中的 placeHoldersLike 字符串。
此版本的代码应按预期工作,您不必担心这里的无限循环。但是,请注意您的占位符,“$”是正则表达式中的保留字符,它们更多是您应该转义的。我假设您所有的占位符都将像“$1”、“$2”等。如果不是,您应该编辑 regexPlaceholder 函数来包装和转义该字符。
let mainString1 = "main string [=12=] ";
let mainString2 = "main string [=12=] ";
let substrings = [
{ placeholderName: "[=12=]", value: " test1 " },
{ placeholderName: "", value: "test2 " },
{ placeholderName: "", value: "test3" },
];
function replacePlaceHolders(mainString, substrings) {
//You will need to escape the $ characters or maybe even others depending of how you made your placeholders
function regexPlaceholder(p) {
return new RegExp('\' + p, "gm")
}
let replacedString = mainString
//We will find every placeHolder, the followin line wil return and array with all of them. Ex: ['', $n']
let placeholders = replacedString.match(/$[0-9]*/gm)
//if there is any placeHolder to replace
if (placeholders !== null && placeholders.length > 0) {
//we will declare some variable to check if the values had something inside that can be
//mistaken for a placeHolder.
//We will store how many of them have we changed and replace them back at the end
let replacedplaceholdersInValues = []
let indexofReplacedValue = 0
placeholders.forEach(placeholder => {
//extrac the value to replace
let value = substrings.filter(x => x.placeholderName === placeholder)[0].value
//find if the value had a posible placeholder inside
let placeholdersInValues = value.match(/$[0-9]*/gm)
if (placeholdersInValues !== null && placeholdersInValues.length > 0) {
placeholdersInValues.forEach(placeholdersInValue => {
//if there are, we will replace them with another mark, so our primary function wont change them
value = value.replace(regexPlaceholder(placeholdersInValue), "<markToReplace" + indexofReplacedValue + ">")
//and store every change to make a rollback later
replacedplaceholdersInValues.push({
placeholderName: placeholdersInValue,
value: "<markToReplace" + indexofReplacedValue + ">"
})
})
indexofReplacedValue++
}
//replace the actual placeholders
replacedString = replacedString.replace(regexPlaceholder(placeholder), value)
})
//if there was some placeholderlike inside the values, we change them back to normal
if (replacedplaceholdersInValues.length > 0) {
replacedplaceholdersInValues.forEach(replaced => {
replacedString = replacedString.replace(replaced.value, replaced.placeholderName)
})
}
}
return replacedString
}
console.log(replacePlaceHolders(mainString1, substrings))
console.log(replacePlaceHolders(mainString2, substrings))
关键是选择一个占位符,在主串和子串中都不可能。我的技巧是使用 non-printable 个字符作为占位符。我最喜欢的是 NUL
字符 (0x00
),因为大多数其他人不会使用它,因为 C/C++ 认为它是字符串的结尾。 Javascript 然而足够强大以处理包含 NUL 的字符串(编码为 unicode \0000):
let mainString1 = "main string [=10=]-0 [=10=]-1";
let mainString2 = "main string [=10=]-0 [=10=]-1";
let substrings = [
{ placeholderName: "[=10=]-0", value: "test1 " },
{ placeholderName: "[=10=]-1", value: "test2" }
];
其余代码无需更改。
请注意,我使用 -
字符来防止 javascript 将您的数字 0
和 1
解释为八进制 [=16=]
的一部分.
如果您像大多数程序员一样厌恶 [=16=]
,那么您可以使用任何其他 non-printing 字符,例如 </code>(标题开始)、<code>007
(使您的终端发出铃声的角色 - 还有 James Bond) 等
如果您确定所有占位符都将遵循 $x
格式,我会使用带有回调的 .replace()
方法:
const result = mainString1.replace(
/$\d+/g,
placeholder => substrings.find(
substring => substring.placeholderName === placeholder
)?.value ?? placeholder
);
// result is "main string test1 test2"