#javascript #регулярные_выражения
Дано: Строка, например, вида такого: "Казнить|, нельзя, помиловать.".
Задача: Разделить строку по запятым, но там, где | (вроде экранирования), запятую
нужно игнорировать.
Т.е. должно вернуть это:
["Казнить|, нельзя", " помиловать."]
Возможно просмотр назад дал бы пользу, но в JS, где мне это нужно сделать, такой
фичи нет.
Максимум что добился - это деление по запятой (/([^,]+)/g, это было легко), без учёта
| (а тут забуксовал) и головная боль.
Заранее благодарен за любую помощь!
UPD:
По большому счёту не важно что будет номинально считаться экранированием запятой
- обратный слэш, пайп или квадратик из ASCII-арта, но некто в ответах упёрся бараном
в новые ворота на свойства экранирования \, поэтому теперь экранирует пайп.
Ответы
Ответ 1
Могу предложить решение с match вместо split:
"Казнить|, нельзя, помиловать.".match(/([^\|,]|\|.)+/g)
# ["Казнить|, нельзя", " помиловать."]
Ответ 2
Давайте отталкиваться от того, что javascript поддерживает негативный просмотр вперед.
Тогда последовательность действий такова:
Развернуть исходную строку
Разбить полученную строку с помощью следующего регулярного выражения:
/,(?![|])/
Развернуть каждый элемент полученного массива совпадений и сам массив совпадений,
чтобы получить искомый результат
Вот код:
// (!!!) Будьте осторожны, используя эту функцию *
var naiveReverse = function(string) {
return string.split('').reverse().join('');
}
var string = "Казнить|, нельзя, помиловать.";
var reversed_array = naiveReverse(string).split(/,(?![|])/);
var result_array = reversed_array.map(function(item) {
return naiveReverse(item);
}).reverse();
Результат:
["Казнить|, нельзя", " помиловать."]
Составлено на основе ответов к этим вопросам на StackOverflow:
Javascript: negative lookbehind equivalent?
* How do you reverse a string in place in JavaScript?
Ответ 3
Вот вам такое уродство:
"Казнить|, нельзя, по,мил|,овать.".replace(/([^\|])\,/g, '$1###').replace(/\|\,/g,',').split('###')
Ответ 4
Увидел что Вы отказались от регулярного выражения и решил предложить вариант, который,
наверное, в тысячу раз быстрее будет -
var text = "Казнить|, нельзя, помиловать.";
function cut(text, search, ignore){
var startIndex = 0,
endIndex = 0,
result = [];
while((endIndex = text.indexOf(search, endIndex)) > -1){
if(text.substring(endIndex, endIndex - 1) != ignore){
result.push(text.substring(startIndex, endIndex));
startIndex = endIndex;
}
endIndex++;
}
result.push(text.substring(startIndex, text.length));
return result;
}
console.log(cut(text, ',', '|')); // [ 'Казнить|, нельзя', ', помиловать.' ]
var text = "Казнить|, нельзя, помиловать.";
function cut(text, search, ignore){
var startIndex = 0,
endIndex = 0,
isNotComplete = true,
isPush = false,
result = [];
while(isNotComplete){
isNotComplete = (endIndex = text.indexOf(search, endIndex)) > -1;
if(isNotComplete && text.substring(endIndex, endIndex - 1) != ignore){
isPush = true;
}else if(!isNotComplete){
isPush = true;
endIndex = text.length;
}
if(isPush){
result.push(text.substring(startIndex, endIndex));
startIndex = endIndex;
isPush = false;
}
endIndex++;
}
return result;
}
console.log(cut(text, ',', '|')); // [ 'Казнить|, нельзя', ', помиловать.' ]