使用javascript基于单个或双位数字符提取子字符串

时间:2017-08-30 08:51:13

标签: javascript string substring

这是一个基于我之前提出的问题Extracting substring from string based on delimiter(接受答案)的新问题

我有一个字符串]d1[)½}06~9N110375286414~1T12345ABCD~D150600~S12345ABCDEF98765}

注意:上例中的}后面有空格

我对以上字符串的分隔符是9N,1T,D,S,我需要在分隔符后提取子字符串,直到它达到~或EOL。

在下面的小提琴中,期望分别为D1S1作为分隔符,而不是DS

我面临两个问题

1)单个字符分隔符问题(DS

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;
}

3 个答案:

答案 0 :(得分: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));




答案 1 :(得分:0)

如果您的字符串始终具有您在问题中显示的格式,则可以将字符串拆分为〜符号,然后仅检查子字符串的前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("} ", "");

上述例子中的替换消除了最后的花括号。但我不完全确定这是否是最优雅的方式。肯定不是最灵活的,所以如果你最后面对大括号+空格以外的任何东西,它当然不会被删除。

在提取这些子字符串并删除第一个数组元素之后,您可以专注于只检查字符串中的第一个字符。

答案 2 :(得分:0)

在您的示例中,~位于子字符串的末尾,它也位于分隔符的开头。

因此,您可以将~用作分隔符本身的一部分,并在正则表达式中使用~9N~1T等来分割字符串。这解决了单个字符分隔符的问题,因为DS现在变为~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;
}