我如何在这个正则表达式中自己编写一种转义字符?

How can I program a kind of escape character myself in this regular expression?

我想实现一个函数,将输入字符串中的各个字符串作为数组输出,例如 "str1|str2@str3":

function myFunc(string) { ... }

然而,对于输入 string,只需要存在 str1str2str3(及其分隔符)都是可选的。为此,我已经编写了一个执行某种拆分的正则表达式。我无法进行(正常)拆分,因为分隔符是不同的字符,而且 str1、str2 和 str3 的顺序也很重要。这有点适合我的正则表达式模式。现在,我正在努力如何扩展这种模式,以便您可以使用 \| 来转义这两个定界符或 \@.

我该如何解决这个问题?

var strings = [
  'meaning',
  'meaning|description',
  'meaning@id',
  'meaning|description@id',
  '|description',
  '|description@id',
  '@id',
  'meaning@id|description',
  'sub1\|sub2',
  'mea\|ning|descri\@ption',
  'mea\@ning@id',
  'meaning|description@identific\|\@ation'
];

var pattern = /^(\w+)(?:\|(\w*))?(?:\@(\w*))?$/ // works without escaping
console.log(pattern.exec(strings[3]));

根据问题定义,字符串0-3和8-11应该有效,其余无效。 myFunc(strings[3]) 并且应该 return ['meaning','description','id'] 并且 myFunc(strings[8]) 应该 return [sub1\|sub2,null,null]

我的猜测是您希望拆分所有字符串,为此我们可能会在 char class 中添加这些分隔符,类似于:

([|@\]+)?([\w]+)

如果我们不这样做,我们可能想这样做以进行验证,否则我们的验证会随着组合的增加而变得非常复杂。

const regex = /([|@\]+)?([\w]+)/gm;
const str = `meaning
meaning|description
meaning@id
meaning|description@id
|description
|description@id
@id
meaning@id|description
sub1\|sub2
mea\|ning|descri\@ption
mea\@ning@id
meaning|description@identific\|\@ation`;
let m;

while ((m = regex.exec(str)) !== null) {
    // This is necessary to avoid infinite loops with zero-width matches
    if (m.index === regex.lastIndex) {
        regex.lastIndex++;
    }
    
    // The result can be accessed through the `m`-variable.
    m.forEach((match, groupIndex) => {
        console.log(`Found match, group ${groupIndex}: ${match}`);
    });
}

Demo

您需要允许 \[|@] 在模式中的 \w 旁边将您的 \w 替换为 (?:\[@|]|\w) 模式:

var strings = [
  'meaning',
  'meaning|description',
  'meaning@id',
  'meaning|description@id',
  '|description',
  '|description@id',
  '@id',
  'meaning@id|description',
  'sub1\|sub2',
  'mea\|ning|descri\@ption',
  'mea\@ning@id',
  'meaning|description@identific\|\@ation'
];

var pattern = /^((?:\[@|]|\w)+)(?:\|((?:\[@|]|\w)*))?(?:@((?:\[@|]|\w)*))?$/;
for (var s of strings) {
   if (pattern.test(s)) {
     console.log(s, "=> MATCHES");
   } else {
     console.log(s, "=> FAIL");
   }
}

图案详情

  • ^ - 字符串开始
  • ((?:\[@|]|\w)+) - 第 1 组:\ 重复 1 次或多次,后跟 @| 或单词 char
  • (?:\|((?:\[@|]|\w)*))? - 匹配 1 次或 0 次出现的可选组
    • \| - 一个 | 字符
    • ((?:\[@|]|\w)*) - 第 2 组:0 次或多次重复 \ 后跟 @| 或单词 char
  • (?:@((?:\[@|]|\w)*))? - 匹配 1 次或 0 次出现的可选组
    • @ - 一个 @ 字符
    • ((?:\[@|]|\w)*) 第 3 组:0 次或多次重复 \ 后跟 @| 或单词 char
  • $ - 字符串结尾。

你要找的好像是这个?

((?:\@|\\||[^\|@])*)*

说明: 匹配包含 "\@""\|" 或除 "@""|" 之外的任何字符的所有集合。

https://regexr.com/4fr68