String.prototype.split() 메서드

String.prototype.split() 메서드

split()String 값의 메서드로, 패턴을 받아 문자열을 그 패턴으로 검색해 정렬된 부분 문자열(substring) 목록으로 나누고, 이 부분 문자열들을 배열에 넣어 반환합니다. 문자열을 구분자 기준으로 분해하는 가장 기본적이면서도 강력한 도구입니다.

출처: String.prototype.split() - MDN Web Docs

본문

개요

split() 메서드는 문자열을 패턴에 따라 나누어 배열로 반환합니다. 구분자로 문자열, 정규 표현식, 또는 Symbol.split 메서드가 있는 객체를 모두 사용할 수 있습니다.

기본적인 사용 예는 다음과 같습니다.

const str = "The quick brown fox jumps over the lazy dog.";

const words = str.split(" ");
console.log(words[3]);
// Expected output: "fox"

const chars = str.split("");
console.log(chars[8]);
// Expected output: "k"

const strCopy = str.split();
console.log(strCopy);
// Expected output: Array ["The quick brown fox jumps over the lazy dog."]

구문(Syntax)

split(separator)
split(separator, limit)

매개변수

  • separator — 각 분할이 일어날 위치를 설명하는 패턴입니다. undefined, 문자열, 또는 Symbol.split 메서드가 있는 객체(대표적으로 정규 표현식)가 될 수 있습니다. separator를 생략하거나 undefined를 전달하면 split()은 호출 문자열을 단일 요소로 가진 배열을 반환합니다. undefined가 아니거나 [Symbol.split]() 메서드가 없는 객체가 아닌 모든 값은 문자열로 강제 변환됩니다.
  • limit (선택) — 배열에 포함될 부분 문자열 수의 한도를 지정하는 음이 아닌 정수입니다. 제공되면 지정된 separator가 나올 때마다 문자열을 나누되, limit만큼의 항목이 배열에 담기면 멈춥니다. 남은 텍스트는 배열에 전혀 포함되지 않습니다.

배열은 한도에 도달하기 전에 문자열의 끝에 도달하면 limit보다 적은 항목을 담을 수 있습니다. limit0이면 []가 반환됩니다.

반환값separator가 문자열이면, 주어진 문자열에서 separator가 나타날 때마다 분할된 문자열의 Array가 반환됩니다. separator가 정규 표현식이면 반환 배열에는 각 separator 일치에 대한 캡처 그룹도 포함됩니다. 캡처 그룹은 일치하지 않을 수 있으며, 그 경우 배열에서 undefined가 됩니다. separator에 커스텀 [Symbol.split]() 메서드가 있으면 그 반환값이 직접 반환됩니다.

설명(Description)

separator가 비어 있지 않은 문자열이면, 타깃 문자열은 그 separator의 모든 일치 지점에서 분할되며 결과에는 separator가 포함되지 않습니다. 예를 들어 탭으로 구분된 값(TSV)을 담은 문자열은 myString.split("\t")처럼 탭 문자를 separator로 전달해 파싱할 수 있습니다. separator가 여러 문자를 포함하면 그 전체 문자 시퀀스가 발견되어야 분할됩니다. separator가 문자열의 시작(또는 끝)에 나타나도 분할 효과가 있어, 반환 배열의 첫(또는 마지막) 위치에 빈(즉 길이 0) 문자열이 나타납니다. separatorstr에 나타나지 않으면 반환 배열은 전체 문자열로 이루어진 한 요소만 담습니다.

separator가 빈 문자열("")이면 str은 각 UTF-16 "문자"의 배열로 변환되며, 결과 문자열 양 끝에는 빈 문자열이 없습니다.

참고: 따라서 "".split("")는 문자열이 separator로 전달되고 limit0이 아닐 때 빈 배열을 만드는 유일한 방법입니다.

경고: 빈 문자열("")이 separator로 사용되면 문자열은 사용자가 인식하는 문자(grapheme cluster)나 유니코드 문자(코드 포인트)가 아니라 UTF-16 코드 단위로 분할됩니다. 이는 서러게이트 쌍(surrogate pairs)을 파괴합니다.

separator가 빈 문자열에 일치하는 정규식이면, 그 일치가 UTF-16 코드 단위로 분할될지 유니코드 코드 포인트로 분할될지는 정규식이 Unicode-aware인지에 달려 있습니다.

"😄😄".split(/(?:)/); // [ "\ud83d", "\ude04", "\ud83d", "\ude04" ]
"😄😄".split(/(?:)/u); // [ "😄", "😄" ]

separator가 캡처 그룹이 있는 정규 표현식이면, separator가 일치할 때마다 캡처 그룹(undefined 결과 포함)이 출력 배열에 이어붙여집니다. 이 동작은 정규식의 Symbol.split 메서드에 의해 지정됩니다.

separatorSymbol.split 메서드를 가진 객체이면, 그 메서드가 타깃 문자열과 limit를 인자로, this를 그 객체로 설정해 호출됩니다. 그 반환값이 split의 반환값이 됩니다. 그 외의 다른 값은 separator로 사용되기 전에 문자열로 강제 변환됩니다.

예제

split() 사용하기 — 문자열이 비어 있고 비어 있지 않은 separator가 지정되면 split()[""]를 반환합니다. 문자열과 separator가 모두 빈 문자열이면 빈 배열이 반환됩니다.

const emptyString = "";

// string is empty and separator is non-empty
console.log(emptyString.split("a"));
// [""]

// string and separator are both empty strings
console.log(emptyString.split(emptyString));
// []

다음 예제는 separator를 사용해 문자열을 문자열 배열로 나누는 함수를 정의합니다. 분할 후 원본 문자열, 사용된 separator, 배열 요소 수, 개별 배열 요소를 로깅합니다.

function splitString(stringToSplit, separator) {
  const arrayOfStrings = stringToSplit.split(separator);

  console.log("The original string is:", stringToSplit);
  console.log("The separator is:", separator);
  console.log(
    "The array has",
    arrayOfStrings.length,
    "elements:",
    arrayOfStrings.join(" / "),
  );
}

const tempestString = "Oh brave new world that has such people in it.";
const monthString = "Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec";

const space = " ";
const comma = ",";

splitString(tempestString, space);
splitString(tempestString);
splitString(monthString, comma);

문자열에서 공백 제거하기 — 다음 예제에서 split()은 0개 이상의 공백, 이어지는 세미콜론, 다시 0개 이상의 공백을 찾아, 발견되면 공백과 세미콜론을 문자열에서 제거합니다. nameListsplit()의 결과로 반환된 배열입니다.

const names = "Harry Trump ;Fred Barney; Helen Rigby ; Bill Abel ;Chris Hand ";

console.log(names);

const re = /\s*(?:;|$)\s*/;
const nameList = names.split(re);

console.log(nameList);
// [ "Harry Trump", "Fred Barney", "Helen Rigby", "Bill Abel", "Chris Hand", "" ]

제한된 수의 분할 반환하기 — 다음 예제에서 split()은 문자열에서 공백을 찾아 처음 3개의 분할을 반환합니다.

const myString = "Hello World. How are you doing?";
const splits = myString.split(" ", 3);

console.log(splits); // [ "Hello", "World.", "How" ]

캡처 그룹을 결과에 포함하는 RegExp로 분할하기separator가 캡처 괄호 ( )를 포함한 정규 표현식이면, 일치된 결과가 배열에 포함됩니다.

const myString = "Hello 1 word. Sentence number 2.";
const splits = myString.split(/(\d)/);

console.log(splits);
// [ "Hello ", "1", " word. Sentence number ", "2", "." ]

참고: \d는 0에서 9 사이 숫자의 문자 클래스와 일치합니다.

커스텀 splitter 사용하기Symbol.split 메서드를 가진 객체를 커스텀 동작을 가진 splitter로 사용할 수 있습니다. 다음 예제는 증가하는 숫자로 이루어진 내부 상태를 사용해 문자열을 분할합니다.

const splitByNumber = {
  [Symbol.split](str) {
    let num = 1;
    let pos = 0;
    const result = [];
    while (pos < str.length) {
      const matchPos = str.indexOf(num, pos);
      if (matchPos === -1) {
        result.push(str.substring(pos));
        break;
      }
      result.push(str.substring(pos, matchPos));
      pos = matchPos + String(num).length;
      num++;
    }
    return result;
  },
};

const myString = "a1bc2c5d3e4f";
console.log(myString.split(splitByNumber)); // [ "a", "bc", "c5d", "e", "f" ]

다음 예제는 내부 상태를 사용해 특정 동작을 강제하고 "유효한" 결과를 만들어냅니다.

const DELIMITER = ";";

// Split the commands, but remove any invalid or unnecessary values.
const splitCommands = {
  [Symbol.split](str, lim) {
    const results = [];
    const state = {
      on: false,
      brightness: {
        current: 2,
        min: 1,
        max: 3,
      },
    };
    let pos = 0;
    let matchPos = str.indexOf(DELIMITER, pos);

    while (matchPos !== -1) {
      const subString = str.slice(pos, matchPos).trim();

      switch (subString) {
        case "light on":
          // If the `on` state is already true, do nothing.
          if (!state.on) {
            state.on = true;
            results.push(subString);
          }
          break;

        case "light off":
          // If the `on` state is already false, do nothing.
          if (state.on) {
            state.on = false;
            results.push(subString);
          }
          break;

        case "brightness up":
          // Enforce a brightness maximum.
          if (state.brightness.current < state.brightness.max) {
            state.brightness.current += 1;
            results.push(subString);
          }
          break;

        case "brightness down":
          // Enforce a brightness minimum.
          if (state.brightness.current > state.brightness.min) {
            state.brightness.current -= 1;
            results.push(subString);
          }
          break;
      }

      if (results.length === lim) {
        break;
      }

      pos = matchPos + DELIMITER.length;
      matchPos = str.indexOf(DELIMITER, pos);
    }

    // If we broke early due to reaching the split `lim`, don't add the remaining commands.
    if (results.length < lim) {
      results.push(str.slice(pos).trim());
    }

    return results;
  },
};

const commands =
  "light on; brightness up; brightness up; brightness up; light on; brightness down; brightness down; light off";
console.log(commands.split(splitCommands, 3)); // ["light on", "brightness up", "brightness down"]

더 알아보기