在组件名称中使用路径定界符时拆分路径

Splitting a path when the path delimiter is used in a component name

这感觉像是一个愚蠢的问题,但我有一个像这样的字符串:

aaaa/bbb\/ccc

\/ 表示路径组件名称中使用的转义分隔符。

因此,该字符串表示两个路径组件 aaaabbb/ccc

此字符串是根据需要从路径组件创建路径的需要生成的,其中需要使用/作为组件之间的分隔符,并且/也可能出现在组件名称中。这就是当 / 出现在组件名称中时需要转义的原因。

可能有两个或更多组件。

使用像 (?:\\/|[^\/])+ 这样的正则表达式接近我正在寻找的内容,但是在考虑字符串 this/is\/a/\/str\/ing 时,它无法将其拆分为组件 thisis\/a & \/str\ & ing.

相反,最终组件被确定为 \/str\/ing

我的问题是 javascript 代码是什么样的,当组件定界符可用于组件名称时,允许我将路径拆分为路径组件?

在上面的示例中,我想以两个字符串 aaaabbb/ccc?

结束

是否有处理此问题的标准函数,或者我是否需要使用正则表达式来帮助我拆分?

谢谢。

const a = String.raw `aaaa/bbb\/ccc/ddd\/eee/fff/ggg`;
console.log(a.replace(/\\//g, "|").split("/").map(x => x.replaceAll("|", "/")));

首先,因为这里涉及到javascript及其转义规则,所以字符串aaaa/bbb\/ccc需要是aaaa/bbb\/ccc.

这是我目前的解决方案:

  //path = "aaaa/\bbb";
  //path = "this/is\/a/dumb/str\\/ing";
  path = "aaaa/bbb\/ccc";
  
  console.log("Path: ", path);

  const matches = path.match(/((?:[^\/\]|\\/|\\|\)+)/g);

  console.log("M: ", matches);

  const pathComponents = matches.reduce((accumulator, component) => {
    component = component.replace("\/", "/");
    accumulator.push(component);
    return accumulator;
  }, []);

  console.log("Path Components: ", pathComponents);
      
  pathComponents.forEach((component) => {
    console.log(`C: ${component}`);
  });
                

我需要 运行 通过第二遍匹配,以便转换匹配:

bbb\/ccc

转换成可以正常显示的东西。如果没有第二遍,它将显示为

bbb\/ccc

需要显示为:

bbb/ccc

案例 #1

path = "aaaa/\bbb";

我看到显示:

C: aaaa
C: \bbb

 

案例 #2

path = "this/is\/a/dumb/str\\/ing";

我看到显示:

C: this
C: is/a
C: dumb
C: str\
C: ing

案例#3(类似于#2)

path = "aaaa/bbb\/ccc";

我看到显示:

C: aaaa
C: bbb/ccc
     

在所有情况下都成功。

我相信我已经抓住了这里所有的边缘情况。

事实证明这比我原先想象的要难。

使用匹配,您可以使用:

(?:[^\n\/\]+|\[\\/]?)+

说明

  • (?: 没有捕获组
    • [^\n\/\]+ 匹配除换行符之外的任何字符 /\
    • |
    • \[\\/]? 匹配 \ 和可选的 \/
  • )+关闭非捕获组并重复1+次

Regex demo

然后在比赛中,您可以将\/替换为/

const regex = /(?:[^\n\/\]+|\[\\/]?)+/g;
[
  String.raw `aaaa/bbb\/ccc`,
  String.raw `this/is\/a/\/str\/ing`,
  String.raw `aaaa/bbb\/ccc/ddd\/eee/fff/ggg`,
  String.raw `this/is\/a/dumb/str\/ing`,
  String.raw `aaaa/\bbb`
].forEach(s =>
  console.log(Array.from(s.matchAll(regex), m => m[0].replace("\/", "/")))
);

如果回顾 is supported,您可以使用 split 和 alternation 来匹配 2 种情况下字符串应该拆分的位置。

然后您可以将 \/ 替换为 / 作为结果数组,例如使用数组 map

(?<=\\)\/|(?<!\)\/

说明

  • (?<=\\)\/ 匹配直接在 \
  • 之前的 /
  • |
  • (?<!\)\/ 当前面没有 \
  • 时匹配 /

Regex demo

[
  String.raw `aaaa/bbb\/ccc`,
  String.raw `this/is\/a/\/str\/ing`,
  String.raw `aaaa/bbb\/ccc/ddd\/eee/fff/ggg`,
  String.raw `this/is\/a/dumb/str\/ing`,
  String.raw `aaaa/\bbb`
].forEach(s => console.log(
  s
  .split(/(?<=\\)\/|(?<!\)\//)
  .map(m => m.replace("\/", "/"))));