如何匹配 {0} 但允许正确转义?

问题描述 投票:0回答:1

我想创建一个简单的文本模板,允许使用

{0}
定义占位符,类似于 .Net 使用 string.format 方法

基本上我想要这个:

  format("{0}", 42), // output `42`
  format("{0} {1}", 42, "bar"), // output `42 bar`
  format("{1} {1}", 42, "bar"), // output `bar bar` ({0} ignored)
  format("{{0", 42), // output `{0` (`{{` is an escaped `{`)
  format("{{{0}", 42), // output `{42` : an escaped brace and the formatted value
  format("Mix {{0}} and {0}", 42), // outputs `Mix {0} and 42`

我正在尝试使用正则表达式和回溯来处理转义的大括号。

function format(template: string, ...values: unknown[]): string {
  const regex = /(?!({{)+){(\d+)}(?<!(}}))/gm;
  return template.replace(regex, ([, index]) => {
    const valueIndex = parseInt(index, 10);
    if (valueIndex >= values.length) throw new Error("Not enough arguments")
    return String(values[valueIndex]);

  });
}

console.log([
  format("{0}", 42), // output `42`
  format("{0} {1}", 42, "bar"), // output `42 bar`
  format("{1} {1}", 42, "bar"), // output `bar bar` ({0} ignored)
  format("{{0", 42), // output `{0` (`{{` is an escaped `{`)
  format("{{{0}", 42), // output `{42` : an escaped brace and the formatted value
  format("Mix {{0}} and {0}", 42), // outputs `Mix {0} and 42`
]);

try {
  format("{0} {1}", 42); // throw error because not enough argument are passed
} catch (e) {
  console.error(e);
}

但是,我正在努力用单个大括号正确替换逃逸的大括号

如何解决?

javascript regex typescript
1个回答
0
投票

你可以使用

(?<=(?<!\{)(?:\{\{)*)\{\d+}(?!(?:}})*}(?!}))

请参阅 正则表达式演示

详情

  • (?<=(?<!\{)(?:\{\{)*)\{
    - 未转义的
    {
    字符(不能有
    {
    后跟零个或多个双
    {
    字符)
  • \d+
  • }(?!(?:}})*}(?!}))
    - 未转义的
    }
    字符(
    }
    前面不能有零个或多个双
    }
    字符)

.replaceAll('{{','{').replaceAll('}}','}')
部分完成变形。

查看 JS 演示:

function format(template, ...values) {
  const regex = /(?<=(?<!\{)(?:\{\{)*)\{\d+}(?!(?:}})*}(?!}))/g;
  return template.replace(regex, ([, index]) => {
    const valueIndex = parseInt(index, 10);
    if (valueIndex >= values.length) throw new Error("Not enough arguments")
    return String(values[valueIndex]).replaceAll('{{','{').replaceAll('}}','}');

  });
}

console.log([
  format("{0}", 42), // output `42`
  format("{0} {1}", 42, "bar"), // output `42 bar`
  format("{1} {1}", 42, "bar"), // output `bar bar` ({0} ignored)
  format("{{0", 42), // output `{0` (`{{` is an escaped `{`)
  format("{{{0}", 42), // output `{42` : an escaped brace and the formatted value
  format("Mix {{0}} and {0}", 42), // outputs `Mix {0} and 42`
]);

try {
  format("{0} {1}", 42); // throw error because not enough argument are passed
} catch (e) {
  console.error(e);
}

© www.soinside.com 2019 - 2024. All rights reserved.