繁体   English   中英

字符串操作 JavaScript - 替换占位符

[英]String manipulation JavaScript - replace placeholders

我有一个很长的字符串,我必须以特定的方式对其进行操作。 该字符串可以包含导致我的代码出现问题的其他子字符串。 因此,对字符串执行任何操作之前,我将所有子字符串(由"引入并以非转义"结尾的任何内容)替换为以下格式的占位符: $0 , $1 , $2 , ..., $n 我确信主字符串本身不包含字符$但子字符串之一(或更多)可能是例如"$0"

现在的问题是:在操作/格式化主字符串后,我需要再次用它们的实际值替换所有占位符。

方便地我将它们保存为这种格式:

// TypeScript
let substrings: { placeholderName: string; value: string }[];

但是做:

 // JavaScript let mainString1 = "main string $0 $1"; let mainString2 = "main string $0 $1"; let substrings = [ { placeholderName: "$0", value: "test1 $1" }, { placeholderName: "$1", 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 $1" console.log(mainString2); // expected result: "main string test1 test2 test2" // wanted result: "main string test1 $1 test2"

不是一个选项,因为子字符串可能包含$x ,它会替换错误的东西(通过.replace()和通过.replaceAll() )。

获取子字符串是用正则表达式存档的,也许正则表达式在这里也有帮助? 虽然我无法控制子字符串中保存的内容......

如果您确定所有占位符都遵循$x格式,我会使用带有回调的.replace()方法:

const result = mainString1.replace(
  /\$\d+/g,
  placeholder => substrings.find(
    substring => substring.placeholderName === placeholder
  )?.value ?? placeholder
);

// result is "main string test1 $1 test2"

这可能不是最有效的代码。 但这是我用评论制作的功能。

注意:要小心,因为如果您将相同的占位符放入其内部,它将创建一个无限循环。 前任:

{ placeholderName: "$1", value: "test2 $1" }

 let mainString1 = "main string $0 $1"; let mainString2 = "main string $0 $1"; let substrings = [{ placeholderName: "$0", value: "test1 $1" }, { placeholderName: "$1", 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: ['$1', $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 字符串被替换。

这个版本的代码应该按预期工作,你不必担心这里的内嵌循环。 但是,请注意您的占位符,“$”是正则表达式中的保留字符,您应该避免使用它们。 我假设你所有的 placeHolders 都会像“$1”、“$2”等。如果不是,你应该编辑 regexPlaceholder 函数来包装和转义那个字符。

 let mainString1 = "main string $0 $1"; let mainString2 = "main string $0 $1 $2"; let substrings = [ { placeholderName: "$0", value: "$1 test1 $2 $1" }, { placeholderName: "$1", value: "test2 $2" }, { placeholderName: "$2", 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: ['$1', $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))

关键是选择一个在主字符串和子字符串中都不可能出现的占位符。 我的技巧是使用不可打印的字符作为占位符。 我最喜欢的是NUL字符( 0x00 ),因为大多数其他人不会使用它,因为 C/C++ 认为它是字符串的结尾。 然而,Javascript 足够强大,可以处理包含 NUL 的字符串(编码为 un​​icode \\0000):

let mainString1 = "main string \0-0 \0-1";
let mainString2 = "main string \0-0 \0-1";

let substrings = [
  { placeholderName: "\0-0", value: "test1 $1" },
  { placeholderName: "\0-1", value: "test2" }
];

其余代码不需要更改。

请注意,我使用-字符来防止 javascript 将您的数字01解释为八进制\\0

如果您像大多数程序员一样厌恶\\0那么您可以使用任何其他非打印字符,如\\1 (标题开头)、 007 (使您的终端发出铃声的字符 - 还有詹姆斯邦德)等。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM