Как исключить из поиска целое слово, включая экранированный символ? - PullRequest
3 голосов
/ 06 июня 2019

Я пытаюсь найти способ сопоставить один символ, кроме случаев, когда он находится внутри определенного слова.

Проблема в том, что я пытаюсь найти все «/», но не те, которые находятся внутри «TCP / IP». Я обнаружил, что Negative Lookahead сделает эту работу, но проблема в том, чтобы исключить слово «TCP / IP» целиком. Когда я избегаю '/', это делает неправильный взгляд неверным.

Проверенное регулярное выражение:

(?!TCP\/IP)\/

Данные для тестирования:

PHP/JAVA/TCP/IP/PYTHON/JAVASCRIPT

Должен совпадать с каждым символом /, кроме того, что внутри TCP / IP.

Тем не менее, когда я тестирую регулярное выражение с помощью regex101.com, моя отрицательная перспектива заглушается, когда я добавляю /:

Negative Lookahead (?!TCP\/IP)
Assert that the Regex below does not match
TCP matches the characters TCP literally (case insensitive)
\/ matches the character / literally (case insensitive)
IP matches the characters IP literally (case insensitive)

Кажется, это больше не рассматривается как одно слово.

Я думаю, что это можно легко исправить, но сейчас я не могу найти решение.

Спасибо.

Ответы [ 5 ]

2 голосов
/ 06 июня 2019

Вместо того, чтобы сопоставлять косые черты, чтобы разделить, вы также можете использовать "обратное" регулярное выражение, чтобы найти все совпадения.

const string = "PHP/JAVA/TCP/IP/PYTHON/JAVASCRIPT";
const regex = /(TCP\/IP)(?=\/|$)|[^/]+/g;
//             ^       ^
// The group is unnecessary here, but is required in my second example.

console.log(string.match(regex));

Если у вас есть больше исключений, вы можете сделать это динамическим, выполнив следующие действия:

const string = "PHP/JAVA/TCP/IP/PYTHON/JAVASCRIPT/AB/CDE/FOO/UDP/TCP/AB/CD";
const exceptions = ["TCP/IP", "AB/CD", "AB/CDE", "UDP/TCP"];

// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#Escaping
function escapeRegExp(string) {
  return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
}

let pattern = exceptions.map(escapeRegExp).join('|');
    pattern = `(${pattern})(?=/|$)|[^/]+`;
const regex = new RegExp(pattern, "g");

console.log(string.match(regex));

Позвольте мне дать краткое изложение того, что это делает.

  1. Сначала экранируйте все специальные символы регулярных выражений в массиве exceptions.
  2. Соедините их вместе с символом | (регулярное выражение ИЛИ).
  3. Теперь для самого регулярного выражения.Подходим одно из исключений.За соответствием должен следовать либо символ /, либо конец строки ($).Если ни одно из исключений не совпадает, проверьте, не является ли символ не /.Если это так, сопоставьте как можно больше не /.

Примечание: Если по каким-то причинам у вас есть исключения A/B и A/B/C, выследует переставить массив так, чтобы A/B/C предшествовал A/B.Если этого не сделать, вы получите совпадения ["A/B", "C"] для строки "A/B/C" из-за того, что за A/B действительно следует косая черта.Сортировка массива по длине строки (по возрастанию в первую очередь) решает эту проблему.

1 голос
/ 06 июня 2019

Так как отрицательные взгляды не полностью поддерживаются, вы можете сопоставить то, что вам не нужно, и захватить то, что вы хотите, в группе захвата.

Ваши значения находятся в первой группе захвата $1

\bTCP\/IP\b|(\/)

Это будет соответствовать:

  • \bTCP\/IP\b Соответствует TCP / IP между границами слов
  • |
  • (!\/) захватить косую черту в группе 1

См. Демонстрацию регулярных выражений

1 голос
/ 06 июня 2019

Нет The "negative lookbehind" feature may not be supported in all browsers. предупреждение.

const string = 'PHP/JAVA/TCP/IP/PYTHON/JAVASCRIPT/ABC/ABDEFIP';
const regex = /\/(?![^TCP]*IP)/g;
const output = string.replace(regex, ' ');

console.log(output);
0 голосов
/ 06 июня 2019

Я не мог найти способ сделать это с помощью регулярного выражения, но альтернативой регулярному выражению было бы просто разделить на /, а затем итерировать полученный массив один раз, чтобы обработать крайний случай записи TCP/IP:

var input = "PHP/JAVA/TCP/IP/PYTHON/JAVASCRIPT"
var parts = input.split("/")
var keep = [];
var flag = false;
for (var i = 0; i < parts.length; i++) {
    if (parts[i] == "TCP") {
        flag = true;
        keep.push(parts[i]);
        continue;
    }
    else if (parts[i] == "IP" && flag) {
        keep.pop();
        keep.push("TCP/IP");
    }
    else {
        keep.push(parts[i]);
    }
    flag = false;
}

console.log(keep);
0 голосов
/ 06 июня 2019

Я смог использовать Regexr для создания Regex, которое соответствует тому, что, как я полагаю, вы спрашиваете - каждый /, который не существует в TCP/IP.

Мне пришлось разделить ваш обходной путь на отрицательный взгляд сзади для TCP ((?<!TCP)), затем / (\/), а затем отрицательный взгляд на IP ((?!IP))

Полученное регулярное выражение равно (?<!TCP)\/(?!IP)

См .: https://regexr.com/4fccb

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...