babsher
babsher

Reputation: 1016

Javascript split only once and ignore the rest

I am parsing some key value pairs that are separated by colons. The problem I am having is that in the value section there are colons that I want to ignore but the split function is picking them up anyway.

sample:

Name: my name
description: this string is not escaped: i hate these colons
date: a date

On the individual lines I tried this line.split(/:/, 1) but it only matched the value part of the data. Next I tried line.split(/:/, 2) but that gave me ['description', 'this string is not escaped'] and I need the whole string.

Thanks for the help!

Upvotes: 13

Views: 13371

Answers (7)

Zing Lee
Zing Lee

Reputation: 730

function splitOnce(str, sep) {
  const idx = str.indexOf(sep);
  return [str.slice(0, idx), str.slice(idx+1)];
}
splitOnce("description: this string is not escaped: i hate these colons", ":")

Upvotes: 0

Roko C. Buljan
Roko C. Buljan

Reputation: 206151

Split string in two at first occurrence

To split a string with multiple i.e. columns : only at the first column occurrence
use Positive Lookbehind (?<=)

const a = "Description: this: is: nice";
const b = "Name: My Name";

console.log(a.split(/(?<=^[^:]*):/)); // ["Description", " this: is: nice"]
console.log(b.split(/(?<=^[^:]*):/)); // ["Name", " My Name"]

it basically consumes from Start of string ^ everything that is not a column [^:] zero or more times *. Once the positive lookbehind is done, finally matches the column :.

If you additionally want to remove one or more whitespaces following the column,
use /(?<=^[^:]*): */

Explanation on Regex101.com

Upvotes: 0

JaredMcAteer
JaredMcAteer

Reputation: 22536

Use the greedy operator (?) to only split the first instance.

line.split(/: (.+)?/, 2);

Upvotes: 15

FlameStorm
FlameStorm

Reputation: 1004

May be this approach will be the best for such purpose:

var a = line.match(/([^:\s]+)\s*:\s*(.*)/);
var key = a[1];
var val = a[2];

So, you can use tabulations in your config/data files of such structure and also not worry about spaces before or after your name-value delimiter ':'.

Or you can use primitive and fast string functions indexOf and substr to reach your goal in, I think, the fastest way (by CPU and RAM)

for ( ... line ... ) {
    var delimPos = line.indexOf(':');
    if (delimPos <= 0) {
        continue; // Something wrong with this "line"
    }
    var key = line.substr(0, delimPos).trim();
    var val = line.substr(delimPos + 1).trim();

    // Do all you need with this  key: val
}

Upvotes: 0

Dabble
Dabble

Reputation: 39

Slightly more elegant:

a = line.match(/(.*?):(.*)/);
key = a[1];
val = a[2];

Upvotes: 1

Paolo
Paolo

Reputation: 21056

If you prefer an alternative to regexp consider this:

var split = line.split(':');
var key = split[0];
var val = split.slice(1).join(":");

Reference: split, slice, join.

Upvotes: 3

awm
awm

Reputation: 6570

a = line.split(/:/);
key = a.shift();
val = a.join(':');

Upvotes: 25

Related Questions