Регулярное выражение, чтобы соответствовать все символы, кроме слова - PullRequest
2 голосов
/ 05 апреля 2019

Как сделать регулярное выражение для сопоставления всех символов, кроме слова?

Нужно найти все символы, кроме слова.

(.*) - найти все символы.

[^v] - он находит все символы, кроме буквы v

Но как найти все символы, кроме слова ?

Решение (записанониже):

((?:(?!here any word for block)[\s\S])*?)

или

((?:(?!here any word for block).)*?)

((?:(?!video)[\s\S])*?)


Я хочу найти все, кроме |end| изаменить все, кроме `| end |.

Я пытаюсь:

Нужно все, кроме |end|

var str = '|video| |end| |water| |sun| |cloud|';
// May be:
//var str = '|end| |video| |water| |sun| |cloud|';
//var str = '|cloud| |video| |water| |sun| |end|';

str.replace(/\|((?!end|end$).*?)\|/gm, test_fun2);

function test_fun2(match, p1, offset, str_full) {
  console.log("--------------");
  p1 = "["+p1+"]";
  console.log(p1);
  console.log("--------------");
  return p1;
}

Журнал консоли вывода:

--------------
[video]
--------------
--------------

--------------
--------------

--------------
--------------

--------------

Пример необходимости:

Любые символы, кроме [video](

вход - '[video](text-1 *******any symbols except: "[video](" ******* [video](text-2 any symbols) [video](text-3 any symbols) [video](text-4 any symbols) [video](text-5 any symbols)'

выход - <div>text-1 *******any symbols except: "[video](" *******</div> <div>text-2 any symbols</div><div>text-3 any symbols</div><div>text-4 any symbols</div><div>text-5 any symbols</div>

Ответы [ 3 ]

4 голосов
/ 05 апреля 2019

Сценарий 1

Используйте лучший трюк за всю историю :

Одним из ключей к этой технике, к которой я несколько раз вернусь, является то, что мы полностью игнорируем общие совпадения, возвращаемые механизмом регулярных выражений: это мусорное ведро. Вместо этого мы проверяем совпадения группы 1, которые, если установлены, содержат то, что мы ищем.

Решение:

s = s.replace(/\|end\||\|([^|]*)\|/g, function ($0, $1) { 
    return $1 ? "[" + $1 + "]" : $0; 
});

Детали

  • \|end\| - |end| соответствует
  • | - или
  • \|([^|]*)\| - | сопоставляется, любые 0+ символов, кроме |, включаются в группу 1, а затем | сопоставляется.

Если группа 1 соответствует ($1 ?), происходит замена, иначе $0, полное совпадение, возвращается к результату.

JS тест:

console.log(
   "|video| |end| |water| |sun| |cloud|".replace(/\|end\||\|([^|]*)\|/g, function ($0, $1) { 
        return $1 ? "[" + $1 + "]" : $0; 
    })
)

Сценарий 2

Используйте

.replace(/\[(?!end])[^\]]*]\(((?:(?!\[video]\()[\s\S])*?)\)/g, '<div>$1</div>')

См. Демоверсию regex

Детали

  • \[ - [ char
  • (?!end]) - нет end] разрешено сразу после текущей позиции
  • [^\]]* - 0+ символов кроме ] и [
  • ] - ] char
  • \( - ( char
  • ((?:(?!\[video])[\s\S])*?) - Группа 1, которая захватывает любой символ ([\s\S]), 0 или более вхождений, но как можно меньше (*?), который не запускает [video]( последовательность символов
  • \) - ) char.
2 голосов
/ 05 апреля 2019

Вы на правильном пути. Вот что вам нужно сделать с регулярным выражением:

var str = '|video| |end| |water| |sun| |cloud|';

console.log(str.replace(/(?!\|end\|)\|(\S*?)\|/gm, test_fun2));

function test_fun2(match, p1, offset, str_full) {
  return "["+p1+"]";
}

И объяснение того, что было не так - у вас был отрицательный взгляд на после | символа. Это означает, что соответствующий движок будет делать следующее:

  1. Совпадение |video|, поскольку с ним работает шаблон
  2. Возьми следующий |
  3. Найдите, что следующий текст - end, который находится в отрицательной перспективе, и отбросьте его.
  4. Возьмите | сразу после end
  5. захватывает пробел и следующий | символ, поскольку он пропускает отрицательный прогноз и также работает с .*?
  6. продолжить захват промежуточных | | последовательностей, потому что | в начале слова было использовано предыдущим соответствием.

Таким образом, вы в конечном итоге соответствуете следующие вещи

var str = '|video| |end| |water| |sun| |cloud|';
           ^^^^^^^     ^^^     ^^^   ^^^
|video| ______|         |       |     |
| | ____________________|       |     |
| | ____________________________|     |
| | __________________________________|

Все, потому что матч |end был отброшен.

Вы можете увидеть это, если распечатаете спички

var str = '|video| |end| |water| |sun| |cloud|';

str.replace(/\|((?!end|end$).*?)\|/gm, test_fun2);

function test_fun2(match, p1, offset, str_full) {
  console.log(match, p1, offset);
}

Вы увидите, что второй, третий и четвертый match - это | | захваченный элемент p1 - - пробел (не очень хорошо отображается, но есть) и смещение, в котором они были найдены были 12, 20, 26

|video| |end| |water| |sun| |cloud|
01234567890123456789012345678901234
            ^       ^     ^
12 _________|       |     |
20 _________________|     |
26 _______________________|

Я сделал вместо этого явный поиск шаблона |end| в негативном прогнозе, а также совпадение только с непробельными символами, чтобы вы больше не брали | |.

Также стоит отметить, что вы можете переместить свою логику фильтрации вместо обратного вызова вместо регулярного выражения. Это упрощает регулярное выражение, но делает вашу замену более сложной. Тем не менее, это справедливый компромисс, так как код обычно легче поддерживать, если у вас более сложные условия:

var str = '|video| |end| |water| |sun| |cloud|';

//capturing word characters - an alternative to "non-whitespace"
console.log(str.replace(/\|(\w*)\|/gm, test_fun2)); 

function test_fun2(match, p1, offset, str_full) {
  if (p1 === 'end') {
    return match;
  } else {
    return "[" + p1 + "]"
  }
}
2 голосов
/ 05 апреля 2019

Нечто подобное лучше сделать за несколько шагов.Кроме того, если вы подбираете что-то, вы должны использовать match.

var str = '|video| |end| |water| |sun| |cloud|';
var matches = str.match(/\|.*?\|/g);

// strip pipe characters...
matches = matches.map(m=>m.slice(1,-1));

// filter out unwanted words
matches = matches.filter(m=>!['end'].includes(m));
           // this allows you to add more filter words easily
           // if you'll only ever need "end", just do (m=>m!='end')

console.log(matches); // ["video","water","sun","cloud"]

Обратите внимание, что это намного легче понять, что происходит, а также намного проще поддерживать и изменять в будущем по мере необходимости..

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