 
			
				19.08.2018, 23:05
			
			
			
		  
	 | 
 
	
		
		
		
			
			| 
			
				
				
				 Интересующийся 
				
				
				
				
	
 
 
 
			 | 
			  | 
			
				
				
					Регистрация: 12.08.2018 
					
					
					
						Сообщений: 18
					 
					
					
			
		
 
		 
		
			 | 
		 
		 
		
	 | 
 
	| 
	
	
		
		
			
			 
				Найти все блоки текста между символами и запомнить их индексы
			 
			
		
		
		
		Всем привет. 
Возникла у меня такая задача, необходимо найти в строке текста, все отрезки текста которые находятся между символами  [color=ЦВЕТ]текст текст текст[/color], запомнить  индекс начала текста ( без блока [color=ЦВЕТ]!) между этими символами и  индекс конца, записать  значение с цветом которое стоит после  color= и удалить из текста этот блок  оставив лишь текст между ним.
 
Суть примерно такая
 Изначальный текст
Оооочень большая строка текста, [color=красный]выделенный текст[/color], еще всякий текст текст текст [color=зелёный]еще выделенный текст[/color]! Ну и тд.
Надо что бы эта строка превратилась в
Оооочень большая строка текста, выделенный текст, еще всякий текст текст текст еще выделенный текст! Ну и тд.
и после ее обработки на выходе получался примерно вот такой массив с информацией
 
// для каждого блока создаётся объект с данными его позиционирования и цвета
     // тут хранится позиция начала текста БЕЗ блока [color] и позиция окончания
var array_action = [
    {index_start_action: 31, index_end_action: 47, color: "красный"}, // индексы с отрезком текста - выделенный текст
    {index_start_action: 78, index_end_action: 98, color: "зелёный"} // индексы с отрезком текста - еще выделенный текст
]
И еще момент, нужен только чистый JS, никаких плагинов библиотек и тд! 
Пожалуйста помогите с решением! Сам уже кучу времени убил, но ничего толкового пока что не получилось...  
		
	
		
		
		
		
		
		
	
		
			
			
	
			
			
			
			
			
				 
			
			
			
			
			
			
				
			
			
			
		 
		
	
	
	 | 
 
 
	 
		 | 
 
 
	
	
	
		
	
		
		
		
			
			 
			
				19.08.2018, 23:25
			
			
			
		  
	 | 
 
	
		
		
		
			
			| 
			
				
				
				 Интересующийся 
				
				
				
				
	
 
 
 
			 | 
			  | 
			
				
				
					Регистрация: 12.08.2018 
					
					
					
						Сообщений: 18
					 
					
					
			
		
 
		 
		
			 | 
		 
		 
		
	 | 
 
	
	
	
		
		
		
		
		
function createActionForText (text) {
  var text_left_border_start = text.indexOf("[color="),
      text_left_border_end = text.indexOf("]", text_left_border_start),
      color = text.slice(text_left_border_start + 7, text_left_border_end),
      text_right_border_start = text.indexOf("[/color"),
      text_right_border_end = text.indexOf("]", text_right_border_start),
      value = text.slice(text_left_border_end + 1, text_right_border_start),
      text_array = text.split("");
  text_array.splice(text_right_border_start, 8);
  text_array.splice(text_left_border_start, color.length + 8);
  return {
    text: text_array.join(""),
    start: text_left_border_end - (color.length + 8),
    end: (text_left_border_end - (color.length + 8)) + value.length,
    color: color
  }
}
console.log(createActionForText(text));
У меня вроде получилось примерно то что надо, но как то уж больно громоздко выглядит, может можно как то поизящнее это сделать?  
		
	
		
		
		
		
		
		
	
		
		
	
	
	 | 
 
 
	 
		 | 
 
 
	
	
	
		
	
		
		
		
			
			 
			
				19.08.2018, 23:28
			
			
			
		  
	 | 
 
	
		
		
		
			  | 
			
			
				
				
				 Профессор 
				
				
				
				
	
 
 
 
			 | 
			  | 
			
				
				
					Регистрация: 25.10.2016 
					
					
					
						Сообщений: 1,013
					 
					
					
			
		
 
		 
		
			 | 
		 
		 
		
	 | 
 
	
	
	
		
		
		
		
		
var rx = /\[color=([^\]]+)\](.*?)(?:\[\/color\]|$)/g;
var array_action = [];
var totalRemove = 0;
var resultStr = str.replace(rx, function(a, color, txt, idx) {
	array_action.push({
		index_start_action: idx - totalRemove,
		index_end_action: idx + txt.length - totalRemove
    });
	totalRemove += color.length + 16;
	return txt;
});
 
		
	
		
		
		
		
		
		
	
		
		
	
	
	 | 
 
 
	 
		 | 
 
 
	
	
	
		
	
		
		
		
			
			 
			
				19.08.2018, 23:37
			
			
			
		  
	 | 
 
	
		
		
		
			
			| 
			
				
				
				 Интересующийся 
				
				
				
				
	
 
 
 
			 | 
			  | 
			
				
				
					Регистрация: 12.08.2018 
					
					
					
						Сообщений: 18
					 
					
					
			
		
 
		 
		
			 | 
		 
		 
		
	 | 
 
	
	
	
		
		
		
		
		Alexandroppolus, Это уже намного лучше! Спасибо большое!    
		
	
		
		
		
		
		
		
	
		
		
	
	
	 | 
 
 
	 
		 | 
 
 
	
	
	
		
	
		
		
		
			
			 
			
				19.08.2018, 23:50
			
			
			
		  
	 | 
 
	
		
		
		
			  | 
			
			
				
				
				 Профессор 
				
				
				
				
	
 
 
 
			 | 
			  | 
			
				
				
					Регистрация: 27.05.2010 
					
					
					
						Сообщений: 33,150
					 
					
					
			
		
 
		 
		
			 | 
		 
		 
		
	 | 
 
	
	
	
		
		
		
		
		Arhitector,
  
<script>
var str = 'Оооочень большая строка текста, [color=красный]выделенный текст[/color], еще всякий текст текст текст [color=зелёный]еще выделенный текст[/color]! Ну и тд.',
reg = /\[([^=]+)=([^\]]+)\]([\S\s]*?)\[\/\1\]/mig,
array_action = [], n = 1;
str = str.replace(reg, function(a,b,c,d,e) {
  var index_start_action = e - n;
  var index_end_action = index_start_action + d.length
  var color = c;
  var obj = {index_start_action : index_start_action, index_end_action : index_end_action, color : color};
  array_action.push(obj);
  n += a.length - d.length;
  return d
});
document.write(str + "<br>" + JSON.stringify(array_action, null, 4))
</script>
 
		
	
		
		
		
		
		
		
	
		
		
	
	
	 | 
 
 
	 
		 | 
 
 
	
	
	
		
	
		
		
		
			
			 
			
				20.08.2018, 00:10
			
			
			
		  
	 | 
 
	
		
		
		
			  | 
			
			
				
				
				 Тлен 
				
				
				
				
	
 
 
 
			 | 
			  | 
			
				
				
					Регистрация: 02.01.2010 
					
					
					
						Сообщений: 6,601
					 
					
					
			
		
 
		 
		
			 | 
		 
		 
		
	 | 
 
	
	
	
		
		
		
		
		Вообще такие вещи делаются  конечным автоматом, но по-быстрому можно и регуляркой нафигачить, как и все ребята выше   
(версия игнорирующая незакрытые тэги и работающая со вложенностью): 
var str = 'Оооочень большая строка текста, [color=красный]выделенный текст[/color], еще всякий текст текст текст [color=зелёный]еще выделенный текст[/color]! Ну и тд.';
var array_action = [];
var shift = 0;
var start = [];
var result = str.replace(/\[(\/?)color(?:\s*=\s*([^\]]+)\s*)?\]/g, function(full, end, color, index){
  if(end){
    if(end = start.pop()){
      end.index_end_action = index - shift;
      array_action.push(end);
    }
  } else {
    start.push({
      index_start_action: index - shift,
      color: color
    })
  }
  shift += full.length;
  return '';
});
console.log(result, array_action);
 
		
	
		
		
		
		
		
			
				__________________ 
				29375, 35 
 
			 
		
		
		
		
		
						  
				
				Последний раз редактировалось Aetae, 20.08.2018 в 00:17.
				
				
			
		
		
	
		
		
	
	
	 | 
 
 
	 
		 | 
 
 
	
	
	
		
	
		
		
		
			
			 
			
				20.08.2018, 00:13
			
			
			
		  
	 | 
 
	
		
		
		
			  | 
			
			
				
				
				 Профессор 
				
				
				
				
	
 
 
 
			 | 
			  | 
			
				
				
					Регистрация: 20.12.2009 
					
					
					
						Сообщений: 1,714
					 
					
					
			
		
 
		 
		
			 | 
		 
		 
		
	 | 
 
	
	
	
		
		
		
		
		Вариант с  String.prototype.match
<!doctype html>
<html>
	<head><style>body { font: 120% sans-serif; }</style></head>
	<body>
		<script>
		
// функция, выдающая строку и объект с данными о позиции цветного текста
function parse(string) {
	var match;
	var spans = [], index = 0, text = [], length;
	while(match = string.match(/(\[color=([^\]]+)\])(.*?)(\[\/color\])/s)) {
		index += match.index;
		text.push(string.slice(0, match.index) + match[3]);
		length = match[0].length - match[1].length - match[4].length;
		spans.push({
			start: index,
			end: index + length,
			color: match[2]
		});
		index += length;
		string = string.slice(match.index + match[0].length);
	}
	text.push(string);
	return {
		text: text.join(""),
		spans
	};
}
// пример, проверка
function stringify({ text, spans }) {
	return spans.reduce((string, { start, end, color }, index, data) => {
		string.push(
			`<mark style="color: ${color};">${text.slice(start, end)}</mark>`
		);
		string.push(
			(index + 1) in data ?
				text.slice(end, data[index + 1].start) :
				text.slice(end)
		);
		return string;
	}, [text.slice(0, 0 in spans ? spans[0].start : Infinity)]).join("");
}
			
var r = parse("Оооочень большая строка текста, [color=red]выделенный текст[/color], еще всякий текст текст текст [color=green]еще выделенный текст[/color]! Ну и тд.");
document.body.innerHTML = `<pre>${JSON.stringify(r, null, "\t")}</pre>` +  stringify(r);
		</script>
	</body>
</html>
 
		
	
		
		
		
		
		
		
	
		
			
			
	
			
			
			
			
			
				 
			
			
			
			
			
			
				
			
			
			
		 
		
	
	
	 | 
 
 
	 
		 | 
 
 
	
	
	
		
	
		
		
		
			
			 
			
				20.08.2018, 00:33
			
			
			
		  
	 | 
 
	
		
		
		
			  | 
			
			
				
				
				 Профессор 
				
				
				
				
	
 
 
 
			 | 
			  | 
			
				
				
					Регистрация: 25.10.2016 
					
					
					
						Сообщений: 1,013
					 
					
					
			
		
 
		 
		
			 | 
		 
		 
		
	 | 
 
	
	
	
		
		
		
		
		
	
 
	| 
		
			Сообщение от Aetae
			
		
	 | 
 
	| 
		работающая со вложенностью
	 | 
 
	
 
 со вложенностью не совсем понятно, какой правильный результат должен быть (автор ничего не говорил об этом)
 
возможно, для строки  
"111[color=green]222[color=red]333[/color]444[/color]555"
  должно быть 3 непересекающихся экшена - green для "222", red для "333", green для "444". Но и там в принципе твой вариант со стеком можно приспособить  
		
	
		
		
		
		
		
		
	
		
		
	
	
	 | 
 
 
	 
		 | 
 
 
 
 |  
  |