Это новый вопрос, основанный на моем ранее заданном вопросе Извлечение подстроки из строки на основе разделителя (ответ принят)

У меня есть строка ]d1[)½}06~9N110375286414~1T12345ABCD~D150600~S12345ABCDEF98765}

Примечание . В приведенном выше примере после } есть пробел

Мои разделители в приведенных выше строках: 9N, 1T, D, S, и мне нужно извлечь подстроки после разделителя, пока он не достигнет ~ или EOL.

В скрипте ниже ожидаются D1 и S1 в качестве разделителей вместо D и S соответственно.

У меня две проблемы

1) Проблема с одним символом-разделителем (D, S)

2) Как мне убрать } в конце строки при возврате значений. Например, подстрока с разделителем S должна вернуть 12345ABCDEF98765 вместо 12345ABCDEF98765}

Fiddle (результаты основаны на консоли)

Js

// Use ]d1[)½}06~9N110375286414~1T12345ABCD~D150600~S12345ABCDEF98765} 
// Note: There is an empty space after the } char as shown above

var dataNames = {
  '9N': 'PPN',
  '1T': 'batchNumber',
  'D': 'expireDate',
  'S': 'serialNumber'
};

var input = document.querySelector("input");
document.querySelector("button").addEventListener("click", function() {
  var str = input.value;
  console.log(parseGS1(str));
});

function parseGS1(str) {
  var fnc1 = "~";
  var data = {};

  //remove ]d1[)½}06~
  str = str.slice(10);

  while (str.length) {
    //get the AI identifier: 1T, 9N etc
    let aiIdent = str.slice(0, 2);
    //get the name we want to use for the data object
    let dataName = dataNames[aiIdent];
    //update the string
    str = str.slice(2);

    switch (aiIdent) {
      case "1T":
      case "9N":
        let fnc1Index = str.indexOf(fnc1);
        //eol or fnc1 cases
        if (fnc1Index == -1) {
          data[dataName] = str.slice(0);
          str = "";
        } else {
          data[dataName] = str.slice(0, fnc1Index);
          str = str.slice(fnc1Index + 1);
        }
        break;
      case "D":
      case "S":

        //eol or fnc1 cases

        break;
      default:
        console.log("unexpected ident encountered:", aiIdent);
        return false;
        break;
    }
  }
  return data;
}
1
zaq 30 Авг 2017 в 11:51

3 ответа

Лучший ответ

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

function getData(input) {
  input = input.slice(0, input.length - 2);
  // The regex has two capture groups. 
  // Group 1 gets the identifier, this can also be the start of the string.
  // Group 2 gets all the characters between the identifier and the '~' char or '} '.
  // The third group is a non-capturing group, it is used to find the delimiter where the next part starts.
  var
      regex = /(^|9N|1T|D|S)(.*?)(?:~|$)/g,
      data = {},
      match = regex.exec(input);

  while (match !== null) {
    switch(match[1]) {
    case '9N':
      data.PPN = match[2];
      break;
    case '1T':
      data.batch = match[2];  
      break;
    case 'D':
      data.expireDate = match[2];  
      break;
    case 'S':
      data.serial = match[2];  
      break;  
    }
    var msg = 'Found ' + match[0] + ' / identifier = ' + match[1]  +  ' / value = ' + match[2] + '. ';
    console.log(msg);

    // Get the next match.
    match = regex.exec(input);
  }
  return data;
}

var input = ']d1[)½}06~9N110375286414~1T12345ABCD~D150600~S12345ABCDEF98765} ',
    input2 = ']d1[)½}06~9N110375286414~D150600~1T12345ABCD~S12345ABCDEF98765} ';
console.log(getData(input));
console.log(getData(input2));
3
Thijs 30 Авг 2017 в 11:30

В вашем примере ~ находится в конце подстроки, а также в начале разделителя.

Поэтому вы можете использовать ~ как часть самого разделителя и использовать ~9N, ~1T и т. Д. В регулярном выражении для разделения строки. Это решает проблему с одиночными разделителями символов, поскольку D и S теперь становятся ~D и ~S.

Вторая проблема решается путем сопоставления с } в регулярном выражении и удаления его из выходных данных, не захватывая его как часть подстроки, следующей за ~S.

Образец кода:

// your input
var str = ']d1[)½}06~9N110375286414~1T12345ABCD~D150600~S12345ABCDEF98765} ';

// regex to parse delimiters
var pattern = /(.*)~9N(.*)~1T(.*)~D(.*)~S(.*)\}/;

// delimiter descriptions
var dataNames = {
  '9N': 'PPN',
  '1T': 'batchNumber',
  'D': 'expireDate',
  'S': 'serialNumber'
};

// test input
console.log(parseGS1(str));

// parse function
function parseGS1(str) {
  // call regex
  var match = pattern.exec(str); // try console.log(match);

  // output object
  var data = {};
  
  // match items 2-5 should be substrings
  data[dataNames['9N']] = match[2];
  data[dataNames['1T']] = match[3];
  data[dataNames['D']] = match[4];
  data[dataNames['S']] = match[5];
  
  return data;
}
0
Robin Mackenzie 30 Авг 2017 в 09:14

Если ваша строка всегда имеет формат, который вы показываете в вопросе, вы можете разбить строку на символ ~, а затем проверить только первые 2 символа подстрок.

var string = "]d1[)½}06~9N110375286414~1T12345ABCD~D150600~S12345ABCDEF98765} "

var substrings = string.split('~');
substrings.shift(); //get rid of irrelevant first array element
substrings[substrings.length-1] = substrings[substrings.length-1].replace("} ", "");

Замена в приведенном выше примере устраняет фигурную скобку на конце. Но я не совсем уверен, что это самый элегантный способ. Это, безусловно, не самый гибкий, поэтому, если вы столкнетесь с чем-то, кроме фигурной скобки + пробела в конце, это, конечно, не будет удалено.

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

0
mpopp 30 Авг 2017 в 09:22