206

I didn't get an optimized regex that split me a String basing into the first white space occurrence:

var str="72 tocirah sneab";

I need to get:

[
    "72",
    "tocirah sneab",
]
frederj
  • 1,483
  • 9
  • 20
Luca
  • 20,399
  • 18
  • 49
  • 70
  • 1
    What do you mean by "optimized"? Does it *have* to be a regex? – Deestan Apr 22 '12 at 22:47
  • 1
    Please take the time to scroll down to @georg's answer -- beautiful http://stackoverflow.com/a/10272828/93910 – Sanjay Manohar Oct 13 '15 at 00:15
  • Its a pity that many of the answers, don't actually answer the question which specifies "white space" not "space". There is also an ambiguity in the definition - as to what happens if the string is either only whitespace, or contains no whitespace. I'll have a go below as I need it myself and none of the answers seem to actually answer you. – Mitra Ardron Aug 14 '20 at 22:51

17 Answers17

425

If you only care about the space character (and not tabs or other whitespace characters) and only care about everything before the first space and everything after the first space, you can do it without a regular expression like this:

str.substring(0, str.indexOf(' ')); // "72"
str.substring(str.indexOf(' ') + 1); // "tocirah sneab"

Note that if there is no space at all, then the first line will return an empty string and the second line will return the entire string. Be sure that is the behavior that you want in that situation (or that that situation will not arise).

Trott
  • 66,479
  • 23
  • 173
  • 212
  • The question asked about "white space" not space, so I'm not sure why this got so many up-votes ? – Mitra Ardron Aug 14 '20 at 22:55
  • 12
    @MitraArdron People tend to upvote answers they find helpful. The fact that this answer only accounts for space and not other whitespace characters is mentioned in the first sentence of the answer. Since the original poster accepted the answer, it seems likely that they intended "white space" to mean "space character" and not "any whitespace character". All that said, posting an answer (or editing to add to an existing answer) to account for all whitespace is a productive and welcome thing to do. – Trott Aug 17 '20 at 04:28
  • 1
    @jost21 I've updated the code to use `str.substring()` and removed all the stuff about how `substr()` is discouraged. Thanks. – Trott Mar 03 '22 at 07:25
79

Javascript doesn't support lookbehinds, so split is not possible. match works:

str.match(/^(\S+)\s(.*)/).slice(1)

Another trick:

str.replace(/\s+/, '\x01').split('\x01')

how about:

[str.replace(/\s.*/, ''), str.replace(/\S+\s/, '')]

and why not

reverse = function (s) { return s.split('').reverse().join('') }
reverse(str).split(/\s(?=\S+$)/).reverse().map(reverse)

or maybe

re = /^\S+\s|.*/g;
[].concat.call(re.exec(str), re.exec(str))

2019 update: as of ES2018, lookbehinds are supported:

str = "72 tocirah sneab"
s = str.split(/(?<=^\S+)\s/)
console.log(s)
georg
  • 211,518
  • 52
  • 313
  • 390
47

In ES6 you can also

let [first, ...second] = str.split(" ")
second = second.join(" ")
user1652176
  • 489
  • 4
  • 5
  • 4
    I liked this quite a bit and it works fine but performance wise it's pretty bad to the most upvoted "substring" solution. just tested it and it's about 10x slower. – tkit Sep 08 '16 at 12:54
  • 1
    It doesn answer the question which specifies "white space" not space. – Mitra Ardron Aug 14 '20 at 22:53
35

Late to the game, I know but there seems to be a very simple way to do this:

const str = "72 tocirah sneab";
const arr = str.split(/ (.*)/);
console.log(arr);

This will leave arr[0] with "72" and arr[1] with "tocirah sneab". Note that arr[2] will be empty, but you can just ignore it.

For reference:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/split#Capturing_parentheses

Dan Dascalescu
  • 143,271
  • 52
  • 317
  • 404
Cliff Stanford
  • 614
  • 7
  • 11
  • 2
    Note that this produces a last blank element. – Benjamin Intal Jun 11 '20 at 17:11
  • 1
    This is great, thanks. To remove the blank element you can limit the split by passing `2` as a second argument, e.g. `str.split(/ (.*)/, 2)` (see [MDN: String.split#limit](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/split#limit)) – som Aug 03 '22 at 06:17
16
var arr = [];             //new storage
str = str.split(' ');     //split by spaces
arr.push(str.shift());    //add the number
arr.push(str.join(' '));  //and the rest of the string

//arr is now:
["72","tocirah sneab"];

but i still think there is a faster way though.

Joseph
  • 117,725
  • 30
  • 181
  • 234
14

georg's solution is nice, but breaks if the string doesn't contain any whitespace. If your strings have a chance of not containing whitespace, it's safer to use .split and capturing groups like so:

str_1 = str.split(/\s(.+)/)[0];  //everything before the first space
str_2 = str.split(/\s(.+)/)[1];  //everything after the first space
fpscolin
  • 393
  • 3
  • 10
11

I'm not sure why all other answers are so complicated, when you can do it all in one line, handling the lack of space as well.

As an example, let's get the first and "rest" components of a name:

const [first, rest] = 'John Von Doe'.split(/\s+(.*)/);
console.log({ first, rest });

// As array
const components = 'Surma'.split(/\s+(.*)/);
console.log(components);
Dan Dascalescu
  • 143,271
  • 52
  • 317
  • 404
10

You can also use .replace to only replace the first occurrence,

​str = str.replace(' ','<br />');

Leaving out the /g.

DEMO

Daedalus
  • 7,586
  • 5
  • 36
  • 61
  • 3
    @DannyHerran .. No it won't? Have you even tested the code? There is no /g modifier. It is not global. [Try testing the code before you purport to know what it does](http://jsfiddle.net/LWCZj/). Tested in the three major browsers as well. I'd like to know why you think what you do. – Daedalus Jul 11 '14 at 20:07
  • That's smart because I have always considered this as a defect. This is the first time I am seeing this is taken advantage of :) – Gogol May 09 '18 at 11:00
3

I have used .split(" ")[0] to get all the characters before space.

productName.split(" ")[0]
R15
  • 13,982
  • 14
  • 97
  • 173
2

Just split the string into an array and glue the parts you need together. This approach is very flexible, it works in many situations and it is easy to reason about. Plus you only need one function call.

arr = str.split(' ');             // ["72", "tocirah", "sneab"]
strA = arr[0];                    // "72"
strB = arr[1] + ' ' + arr[2];     // "tocirah sneab"

Alternatively, if you want to cherry-pick what you need directly from the string you could do something like this:

strA = str.split(' ')[0];                    // "72";
strB = str.slice(strA.length + 1);           // "tocirah sneab"

Or like this:

strA = str.split(' ')[0];                    // "72";
strB = str.split(' ').splice(1).join(' ');   // "tocirah sneab"

However I suggest the first example.

Working demo: jsbin

Rotareti
  • 49,483
  • 23
  • 112
  • 108
2

Another simple way:

str = 'text1 text2 text3';
strFirstWord = str.split(' ')[0];
strOtherWords = str.replace(strFirstWord + ' ', '');

Result:

strFirstWord = 'text1';
strOtherWords = 'text2 text3';
Lev K.
  • 344
  • 4
  • 4
0

Whenever I need to get a class from a list of classes or a part of a class name or id, I always use split() then either get it specifically with the array index or, most often in my case, pop() to get the last element or shift() to get the first.

This example gets the div's classes "gallery_148 ui-sortable" and returns the gallery id 148.

var galleryClass = $(this).parent().prop("class"); // = gallery_148 ui-sortable
var galleryID = galleryClass.split(" ").shift(); // = gallery_148
galleryID = galleryID.split("_").pop(); // = 148
//or
galleryID = galleryID.substring(8); // = 148 also, but less versatile 

I'm sure it could be compacted into less lines but I left it expanded for readability.

acarito
  • 634
  • 7
  • 15
0

I needed a slightly different result.

I wanted the first word, and what ever came after it - even if it was blank.

str.substr(0, text.indexOf(' ') == -1 ? text.length : text.indexOf(' '));
str.substr(text.indexOf(' ') == -1 ? text.length : text.indexOf(' ') + 1);

so if the input is oneword you get oneword and ''.

If the input is one word and some more you get one and word and some more.

Jim Richards
  • 708
  • 1
  • 7
  • 19
0

Most of the answers above search by space, not whitespace. @georg's answer is good. I have a slightly different version.

s.trim().split(/\s(.*)/).splice(0,2)

I'm not sure how to tell which is most efficient as the regexp in mine is a lot simpler, but it has the extra splace.

(@georg's for reference is s.split(/(?<=^\S+)\s/))

The question doesn't specify how to handle no whitespace or all whitespace, leading or trailing whitespace or an empty string, and our results differ subtly in those cases.

I'm writing this for a parser that needs to consume the next word, so I prefer my definition, though @georg's may be better for other use cases.

input.        mine              @georg
'aaa bbb'     ['aaa','bbb']     ['aaa','bbb']
'aaa bbb ccc' ['aaa','bbb ccc'] ['aaa','bbb ccc']
'aaa '        [ 'aaa' ]         [ 'aaa', '' ]
' '           [ '' ]            [ ' ' ]
''            ['']              ['']
' aaa'        ['aaa']           [' aaa']
Mitra Ardron
  • 343
  • 2
  • 8
  • I think I should withdraw this answer in favor of @georg's - I still think this answer is going to be more efficient for space delimited strings, but it doesn't handle strings with \n in. – Mitra Ardron Aug 20 '20 at 09:00
0
"72 tocirah sneab".split(/ (.*)/,2)

produces the specified result

[ '72', 'tocirah sneab' ]
Jonathan
  • 1,007
  • 16
  • 12
0

If purpose is just to get first substring before space then below is best case and it will not return empty if no space is there.

var str = "string1 string2";
str = str.trim();
if(str.indexOf(' ')!==-1)
 str = str.substring(0, str.indexOf(' ')); 
-1

The following function will always split the sentence into 2 elements. The first element will contain only the first word and the second element will contain all the other words (or it will be a empty string).

var arr1 = split_on_first_word("72 tocirah sneab");       // Result: ["72", "tocirah sneab"]
var arr2 = split_on_first_word("  72  tocirah sneab  ");  // Result: ["72", "tocirah sneab"]
var arr3 = split_on_first_word("72");                     // Result: ["72", ""]
var arr4 = split_on_first_word("");                       // Result: ["", ""]

function split_on_first_word(str)
{
    str = str.trim();  // Clean string by removing beginning and ending spaces.

    var arr = [];
    var pos = str.indexOf(' ');  // Find position of first space

    if ( pos === -1 ) {
        // No space found
        arr.push(str);                // First word (or empty)
        arr.push('');                 // Empty (no next words)
    } else {
        // Split on first space
        arr.push(str.substr(0,pos));         // First word
        arr.push(str.substr(pos+1).trim());  // Next words
    }

    return arr;
}
Sjoerd Linders
  • 447
  • 5
  • 8