Подстрока JavaScript из строки с переменным содержимым

#javascript #string #substring

#javascript #строка #подстрока

Вопрос:

У меня есть строка, которая может содержать различные биты информации, мне нужно подстрочить GUID из этого, когда я не могу быть уверен в позиции GUID в строке.

Возможные версии строки

stringVar=email:name@company.com amp;номер:b83edd0d-fec5-4ec0-8055-60bc0d8eb4b6;

stringVar=email:name@company.com amp;номер:b83edd0d-fec5-4ec0-8055-60bc0d8eb4b6amp;host=ИМЯ ХОСТА;

stringVar=email:name@company.comamp;location=SomeCity amp;номер:b83edd0d-fec5-4ec0-8055-60bc0d8eb4b6;

Существует несколько других перестановок строки с большим или меньшим количеством полей, она всегда будет, по крайней мере, содержать GUID.

Приблизительная версия того, что у меня есть:

 var room = str.substring(str.lastIndex(room),str.lastIndex(;))
if room.length !== 36
    var room = str.substring(str.lastIndex(room),str.lastIndexOf(amp;)
  

Должен быть более чистый способ сделать это?

Комментарии:

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

2. Другой способ использовать регулярное выражение stringVar.match(/room:([a-zA-Z0-9-] )/)[1]

3. Почему у какой-то пары ключ-значение есть = , а у какой-то есть : . Это намеренно?

4. @Rajesh на самом деле это переменная cookie проприетарной системы, поэтому я, к сожалению, застрял с ней.

5. @haddow64 Я попытался добавить универсальную функцию для анализа вашего формата. Не идеально, но должно помочь.

Ответ №1:

Должен быть более чистый способ сделать это?

Существует — REGEX.

 var guid = str.match(/room:([^amp;] )/);
  

Совпадение, если оно найдено, будет сохранено в guid[0] , только с идентификатором guid (минус «room:») в guid[1] .

Комментарии:

1. Спасибо, хороший и понятный способ сделать это.

Ответ №2:

Вы можете просто использовать манипулирование строками, например:

 var stringVar1 = "email:name@company.comamp;room:b83edd0d-fec5-4ec0-8055-60bc0d8eb4b6";
var stringVar2 = "email:name@company.comamp;room:b83edd0d-fec5-4ec0-8055-60bc0d8eb4b6amp;host=HOSTNAME";
var stringVar3 = "email:name@company.comamp;location=SomeCityamp;room:b83edd0d-fec5-4ec0-8055-60bc0d8eb4b6";

function getRoomId(input) {
  return input
    .split("amp;") //separate into chunks 
    .find(part => part.startsWith("room:")) //see which starts with room
    .split(":")[1]; //split and return the second part, which is the GUID
}
console.log(getRoomId(stringVar1));
console.log(getRoomId(stringVar2));
console.log(getRoomId(stringVar3));  

Альтернативно, более «тупой» способ — просто обрезать нужную строку. Основным недостатком является то, что это выглядит не так «модно», но, с другой стороны, это будет работать во всех браузерах.

 var stringVar1 = "email:name@company.comamp;room:b83edd0d-fec5-4ec0-8055-60bc0d8eb4b6";
var stringVar2 = "email:name@company.comamp;room:b83edd0d-fec5-4ec0-8055-60bc0d8eb4b6amp;host=HOSTNAME";
var stringVar3 = "email:name@company.comamp;location=SomeCityamp;room:b83edd0d-fec5-4ec0-8055-60bc0d8eb4b6";

function getRoomId(input) {
  return input
    .split("room:")[1] //find the part of the string that starts with "room:" and cut there
    .split("amp;", 1)[0]; //cut again at the next "amp;" and return the first part
}
console.log(getRoomId(stringVar1));
console.log(getRoomId(stringVar2));
console.log(getRoomId(stringVar3));  

Наконец, вы можете выполнить еще более простой поиск значений, который также будет работать во всех браузерах:

 var stringVar1 = "email:name@company.comamp;room:b83edd0d-fec5-4ec0-8055-60bc0d8eb4b6";
var stringVar2 = "email:name@company.comamp;room:b83edd0d-fec5-4ec0-8055-60bc0d8eb4b6amp;host=HOSTNAME";
var stringVar3 = "email:name@company.comamp;location=SomeCityamp;room:b83edd0d-fec5-4ec0-8055-60bc0d8eb4b6";

function getRoomId(input) {
  var start = input.indexOf("room:")   5; //the index is the beginning of "room:", so add 5 characters to get rid of it
  var end = input.indexOf("amp;", start); //the next "amp;" after "room:" will be after the GUID
  end = end !== -1? end : input.length; //if there is no next "amp;", then grab everything until the end of the string
  
  return input.slice(start, end);
}
console.log(getRoomId(stringVar1));
console.log(getRoomId(stringVar2));
console.log(getRoomId(stringVar3));  

Существуют и другие варианты, но идея в том, что это достаточно просто решить, обработав это как строку.

Ответ №3:

Используйте это регулярное выражение

 /(room:[a-zA-Z0-9] -[a-zA-Z0-9] -[a-zA-Z0-9] -[0-9] -[a-zA-Z0-9] )/
  

это соответствовало бы следующим данным:

 room:b83edd0d-fec5-4ec0-8055-60bc0d8eb4b6  
room:b83edd0d-fec5-4ec0-8055-60bc0d8eb4b6  
room:b83edd0d-fec5-4ec0-8055-60bc0d8eb4b6  
  

Вот соответствие: демо

Ответ №4:

Ваш guid ‘room’ содержит только шестнадцатеричные символы. Используйте простое регулярное выражение соответствия, чтобы получить то, что вам нужно:

 /amp;room:([a-fd-] )/i
  

и если room может отображаться как первое поле в строке (в ее начале), вы можете улучшить его, чтобы оно также соответствовало началу строки:

 /(?:^|amp;)room:([a-fd-] )/i
  ^^^^
  

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

Подробные сведения:

  • amp;room: — соответствует буквенной последовательности символов amp;room: ( (?:^|amp;) это группа чередований, соответствующая либо начальной позиции строки ( ^ ), либо ( | ) amp; символу)
  • ([a-fd-] ) — сопоставляет и захватывает в группу 1 один или более символов, которые являются буквами ASCII в диапазонах a-f и A-F (поскольку /i модификатор режима не учитывает регистр), цифр ( d ) или - .

 var strngs = ['stringVar=email:name@company.comamp;room:b83edd0d-fec5-4ec0-8055-60bc0d8eb4b6;', 'stringVar=email:name@company.comamp;room:b83edd0d-fec5-4ec0-8055-60bc0d8eb4b6amp;host=HOSTNAME;', 'stringVar=email:name@company.comamp;location=SomeCityamp;room:b83edd0d-fec5-4ec0-8055-60bc0d8eb4b6;'];
var re = /amp;room:([a-fd-] )/i;
for (var s of strngs) {
  var res = (m=s.match(re)) ? m[1] : "";
  console.log(s   "n=>n"   res); // demo
}  

Ответ №5:

 var str = "email:name@company.comamp;room:b83edd0d-fec5-4ec0-8055-60bc0d8eb4b6;";
var room = str.split("room:")[str.split("room:").length-1].split("amp;")[0].split(";")[0];
//b83edd0d-fec5-4ec0-8055-60bc0d8eb4b6  

Комментарии:

1. Вы можете использовать .pop вместо [str.split("room:").length-1]

Ответ №6:

Я попытался создать функцию, которая возвращала бы вам объект.

Примечание: Я немного изменил формат. Я добавил city:SomeCity в третьем формате.

Базовый формат заключается в том, что у вас может быть = который будет иметь либо строковое значение, либо объект, но не оба сразу. Итак, amp;host=HOSTNAME это нормально, но location=SomeCityamp;room:b83edd0d-fec5-4ec0-8055-60bc0d8eb4b6 это не так, и я изменил ее на location=city:SomeCityamp;room:b83edd0d-fec5-4ec0-8055-60bc0d8eb4b6;

Точка — это значение после того, как оно = должно либо содержаться : для каждой пары, либо его нет.

Пример

 function getObjectFromCookieStr(str){
	var r = {};
  str.split("=").reduce(function(p,c){
  	var k = ''
  	var o = c.split('amp;').reduce(function(p,c){
    	if(c.indexOf(':') > -1){
      	var kv = c.split(':');
        p[kv[0]] = kv[1]
      }
      else{
      	k=c;
      }
      return p;
    }, {});
    r[p] = Object.keys(o).length >0 ? o : c
    return k;
  });
  return r;
}

var s1 = "stringVar=email:name@company.comamp;room:b83edd0d-fec5-4ec0-8055-60bc0d8eb4b6"
var s2 = "stringVar=email:name@company.comamp;room:b83edd0d-fec5-4ec0-8055-60bc0d8eb4b6amp;host=HOSTNAME";
var s3 = "stringVar=email:name@company.comamp;location=city:SomeCityamp;room:b83edd0d-fec5-4ec0-8055-60bc0d8eb4b6";

console.log(getObjectFromCookieStr(s1))
console.log(getObjectFromCookieStr(s2))
console.log(getObjectFromCookieStr(s3))  

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

 function searchKeyInObj(obj, searckKey) {
  if (JSON.stringify(obj).indexOf(searckKey) < 0) return;
  for (var k in obj) {
    if (typeof(obj[k]) === 'object') {
      var v = searchKeyInObj(obj[k], searckKey);
      if (v) return v
    } else if (k === searckKey) {
      return obj[k];
    }
  }
}  

Вы можете протестировать ее на следующем JSFiddle

Ответ №7:

Регулярное выражение — хороший вариант, но это затрудняет чтение кода.

 var stringValue = "stringVar=email:name@company.comamp;room:b83edd0d-fec5-4ec0-8055-60bc0d8eb4b6amp;host=HOSTNAME;"

var pattern = /[da-zA-Z]{8}-([da-zA-Z]{4}-){3}[da-zA-Z]{12}/;

var found = stringValue.match(pattern)

console.log(found[0]);  

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

http://regexr.com/3amuu