Как я могу запрограммировать своего рода экранирующий персонаж в этом регулярном выражении? - PullRequest
2 голосов
/ 14 июня 2019

Я хочу реализовать функцию, которая выводит соответствующие строки в виде массива из входной строки, такой как "str1 | str2 @ str3":

function myFunc(string) { ... }

Для ввода string, однако, этонеобходимо только, чтобы str1 присутствовал.str2 и str3 (с их разделителями) являются необязательными.Для этого я уже написал регулярное выражение, которое выполняет своего рода разделение.Я не могу сделать (нормальное) разделение, потому что разделителями являются разные символы, а также важен порядок 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]) и должен вернуть ['meaning','description','id'], а myFunc(strings[8]) должен вернуть [sub1\|sub2,null,null]

Ответы [ 3 ]

0 голосов
/ 14 июня 2019

Вам необходимо разрешить \\[|@] alognside \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 вхождениям
    • \| - | char
    • ((?:\\[@|]|\w)*) - группа 2: 0 или более повторений \, за которыми следует @ или | или слово char
  • (?:@((?:\\[@|]|\w)*))? - необязательная группа, соответствующая 1 или 0 вхождениям
    • @ - @ char
    • ((?:\\[@|]|\w)*) Группа 3: 0 или более повторений \, за которыми следует @ или | или слово char
  • $ - конец строки.
0 голосов
/ 14 июня 2019

Похоже, то, что вы ищете, может быть таким?

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

Объяснение: Соответствует всем наборам, которые включают "\@", "\|", или любому символу, кроме "@" и "|",

https://regexr.com/4fr68

0 голосов
/ 14 июня 2019

Я предполагаю, что вы хотите разделить все ваши строки, для которых мы бы добавили эти разделители в класс char, например, как:

([|@\\]+)?([\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}`);
    });
}

Демо

...