使用RegEx模式将字符串拆分为数组

时间:2015-04-27 13:18:22

标签: javascript regex

我有一个字符串,我想拆分成一个数组。字符串如下所示:

'O:BED,N:KET,OT,N:JAB,FA,O:RPT,'

字符串可以包含任意数量的对象,例如

'O:BED,N:KET,OT,N:JAB,FA,O:RPT,X:BLA,GTO'

我想将此字符串拆分为\w:的实例,例如O:

所以我最终会得到这样的数组:

['O:BED','N:KET, OT','N:JAB,FA','O:RPT']

我使用以下代码:

var array = st.split(/^(\w:.+)(?=\w:)/g);

但是我最终得到这样的数组:

['','O:BED,N:KET,OT,N:JAB,FA,','O:RPT,']

似乎正则表达式是贪婪的,我该怎么做才能解决它?

注意我正在使用angularjs,最终我想最终得到这个:

   var objs = [
     {type:O,code: BED, suf: ''},
     {type:N, code: KET, suf: OT},
     {type:N, code: JAB, suf: FA},
     {type:O, code: RPT, suf: ''}
     ]

5 个答案:

答案 0 :(得分:2)

如果您的字符串格式正确将会容易得多。但我们仍然可以通过额外的努力来完成任务。希望以下代码适合您。

var str = 'O:BED,N:KET,OT,N:JAB,FA,O:RPT,X:BLA,GTO';

var a = str.split(',');
var objs = [], obj, item, suf;

for(var i=0; i<a.length;){
  item = a[i].split(':');

  if(a[i+1] && a[i+1].indexOf(':') == -1){
    suf = a[i+1];
    i++;
  }else{
    suf = "";
  }

  obj = {
    type: item[0],
    code: item[1],
    suf: suf
  };

  objs.push(obj);
  i++;
}

console.log(objs);

答案 1 :(得分:1)

您可以使用RegExp.prototype.exec方法获取连续匹配,而不是使用分隔符拆分字符串:

var myStr = 'O:BED,N:KET,OT,N:JAB,FA,O:RPT,';
var myRe = /([^,:]+):([^,:]+)(?:,([^,:]+))??(?=,[^,:]+:|,?$)/g;
var m;
var result = [];

while ((m = myRe.exec(myStr)) !== null) {
  result.push({type:m[1], code:m[2], suf:((m[3])?m[3]:'')});
}

console.log(result);

答案 2 :(得分:0)

你想做一个string match,然后迭代它。

AngularJS中的完整示例:http://jsfiddle.net/184cyspg/1/

var myString = 'O:BED,N:KET,OT,N:JAB,FA,O:RPT,';
$scope.myArray = [];
var objs = myString.match(/([A-Z])\:([A-Z]*)\,([A-Z]?)/g);
objs.forEach(function (entry) {
    var obj = entry.replace(',', ':');
    obj = obj.split(':');
    $scope.myArray.push({type: obj[0], code: obj[1], suf: obj[2]});
});

答案 3 :(得分:0)

我喜欢正则表达式:)

如果要在所有匹配项中使用全局标记和exec(),这将匹配字符串的每个对象:

(\w):(\w+)(?:,((?!\w:)\w+))?

唯一真正的诀窍是只将逗号之后的下一位作为后一位处理,如果它看起来不像下一位的类型。

每场比赛都会抓住小组:

  1. SUF
  2. 如果你只想按照你所说的那样split,那么你贪婪问题的解决办法是告诉它在逗号上拆分,然后是那些匹配的对象,例如:

    ,(?=(\w):(\w+)(?:,((?!\w:)\w+))?)
    

答案 4 :(得分:0)

以下内容并未解决您的正则表达式问题,但是引入underscorejs来处理从简单操作到更复杂操作的替代方法。虽然在这种情况下有点矫枉过正;

// ie. input string = 'O:BED,N:KET,OT,N:JAB,FA,O:RPT,';
.controller('AppCtrl', [function() {
    /**
     * Split by comma then (chain) eval each (map) 
     * element that (if-else) contains '0:' is pushed 
     * into array as a new element, otherwise concat element
     * 
     * :#replace hardcoded values with params
     *
     * @param String string - a string to split
     * @param String prefix - prefix to determine start of new array element ie. '0:'
     * @param String delimiter - delimiter to split string ie ','
     * @return Array array of elements by prefix
     */
    $scope.splitter = function(string) {
      var a = [];
      var tmp = "";

      _.chain(string.split(',')) 
        .map(function(element) {
          if(element.indexOf('O:') >= 0) {
            element += tmp;
            a.push(element);
            tmp = "";
          } else {
            tmp += element;
          }
        });

      return a;
    };
}]);

输出:

array: Array[2]
  0: "O:BED"
  1: "O:RPTN:KETOTN:JABFA"
length: 2

更新:刚刚阅读了对象的要求。 underscorejs允许链接操作。例如,可以调整上面的代码来处理对象,链接到.compact().object().value()以产生输出为Object k:v对;

希望这有帮助。