Вы на правильном пути. Вот что вам нужно сделать с регулярным выражением:
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+"]";
}
И объяснение того, что было не так - у вас был отрицательный взгляд на после |
символа. Это означает, что соответствующий движок будет делать следующее:
- Совпадение
|video|
, поскольку с ним работает шаблон
- Возьми следующий
|
- Найдите, что следующий текст -
end
, который находится в отрицательной перспективе, и отбросьте его.
- Возьмите
|
сразу после end
- захватывает пробел и следующий
|
символ, поскольку он пропускает отрицательный прогноз и также работает с .*?
- продолжить захват промежуточных
| |
последовательностей, потому что |
в начале слова было использовано предыдущим соответствием.
Таким образом, вы в конечном итоге соответствуете следующие вещи
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 + "]"
}
}