지정된 문자의 첫 번째 인스턴스에서만 문자열 분리


271

내 코드에서는 _배열을 기반으로 문자열을 분할 하고 두 번째 항목을 가져옵니다.

var element = $(this).attr('class');
var field = element.split('_')[1];

소요 good_luck와 저를 제공합니다 luck. 잘 작동합니다!

그러나 이제는 다음과 같은 클래스가 good_luck_buddy있습니다. Javascript에서 두 번째를 무시하고 _나에게 luck_buddy어떻게 주어야 합니까?

var field = element.split(new char [] {'_'}, 2);ac # stackoverflow 답변 에서 이것을 찾았 지만 작동하지 않습니다. jsFiddle에서 다시 시도했습니다 ...

답변:


406

캡처 괄호를 사용하십시오 .

"good_luck_buddy".split(/_(.+)/)[1]
"luck_buddy"

그들은 다음과 같이 정의됩니다

separator캡처 괄호가 포함 된 경우 일치하는 결과가 배열에 반환됩니다.

따라서이 경우에는 우리는에 분할 할 _.+(즉, 분할 구분 하위 문자열로 시작되는 _) 뿐만 아니라 결과가 우리 분리기의 일부 (예를 포함 할 수 있도록 모든 후를 _).

이 예에서 구분 기호 (일치 _(.+))는 _luck_buddy캡처 된 그룹 (구분 기호 내)입니다 lucky_buddy. 캡처 괄호가 없으면 luck_buddy(matching .+)은 결과 split에 구분 기호가 포함되지 않은 간단한 결과 배열이므로 결과 배열에 포함되지 않습니다.


21
당신은 (?)조차 필요하지 않습니다. 첫 번째 _ 이후에 /_(.+)/를 사용하여 첫 번째 문자를 한 번 더 캡처하십시오
Mark

3
매우 우아합니다. 매력처럼 작동합니다. 감사합니다.
Ofeargall

12
분명히이 솔루션이 작동하는 이유는 첫 번째 이후의 모든 항목 _이 캡처 그룹 내에서 일치하고 해당 이유로 토큰 목록에 추가되기 때문입니다.
Alan Moore

28
에 : :이와 함께 여분의 빈 문자열 요소를 얻는 이유는 누구나 알고 "Aspect Ratio: 16:9".split(/:(.+)/)아웃 :["Aspect Ratio", " 16:9", ""]
케이티 lavallee

4
@katylavallee-도움이 될 수 있습니다 : stackoverflow.com/questions/12836062/… 구분 기호가이므로 구분 기호 ": 16:9"뒤에 아무 것도 없으므로 끝에 빈 문자열이 만들어집니다.
Derek 朕 會 功夫

231

정규 표현식과 배열에는 무엇이 필요합니까?

myString = myString.substring(myString.indexOf('_')+1)

var myString= "hello_there_how_are_you"
myString = myString.substring(myString.indexOf('_')+1)
console.log(myString)


5
문자열! == 문자열. 자바 스크립트는 대소 문자를 구분합니다.
kennebec

3
이것이 가장 좋은 대답이라고 생각합니다. 다음과 같이 _작성하여 문자열을 얻을 수도 있습니다 .myString.substring( myString.indexOf('_', myString().indexOf('_') + 1) + 1 )
muratgozel

9
답은 문자열의 두 번째 부분을 출력합니다. 첫 번째 부분도 원하는 경우 어떻게합니까? 함께 var str = "good_luck_buddy", res = str.split(/_(.+)/);하면 모든 부분을 얻을 :console.log(res[0]); console.log(res[1]);

1
@PeterLeger let split = [ string.substring(0, string.indexOf(options.divider)), string.substring(string.indexOf(options.divider) + 1) ]거기 있습니다. 또한 가변 바늘 지원
Steffan

이것은 천재입니다!
stuckedoverflow 18

36

모든 비용으로 RegExp를 피합니다. 할 수있는 또 다른 일이 있습니다.

"good_luck_buddy".split('_').slice(1).join('_')

18
RegExp를 두려워하는 사람은 RegExp가 얼마나 훌륭한 지 결코 알 수 없습니다. 문을 직접 찾아야합니다. 일단 당신이 거기에 다시 돌아 보지 않을 것입니다. 몇 년 후에 다시 물어 보면 얼마나 큰지 알려줄 것입니다.
Christiaan Westerbeek

3
@yonas 빨간 약을 먹어라!
frnhr

2
@yonas 그래, 빨간 약을 먹어! 줄이 짧아도 인생이 더 빨라질 것입니다 : jsperf.com/split-by-first-colon
Julian F. Weinert

15
하아! 나는 4 년 전에이 의견을 썼습니다. 나는 지금 RegExp에 확실히 탑승하고 있습니다! :)
yonas

2
@yonas 당신은 더 나은하지 않습니다. RegExp는 필요할 때 대단 합니다 . 여기서는 그렇지 않습니다. 업데이트 된 테스트를 확인 : jsperf.com/split-by-first-colon/2
metalim

11

첫 번째 인스턴스를 고유 한 자리 표시 자로 바꾸고 거기서 분리하십시오.

"good_luck_buddy".replace(/\_/,'&').split('&')

["good","luck_buddy"]

분할의 양쪽이 필요할 때 더 유용합니다.


2
이것은 문자열에 불필요한 제약을가합니다.
Yan Foto

위의 모든 답변이 그렇지 않은 경우이 답변이 효과적이었습니다.
GuitarViking

1
@YanFoto '&'를 사용한다는 의미입니까? 무엇이든 될 수 있습니다.
sebjwallace

2
@sebjwallace 무엇을 선택하든 문자열에 해당 문자를 가질 수 없습니다. 예를 들어 "fish & chips_are_great"는 [fish, chips, are_great]라고 생각합니다.
Joe

@Joe '&'대신 무엇이든 사용할 수 있습니다. 이것은 단지 예일뿐입니다. 원한다면 _의 첫 번째 항목을 ¬로 바꿀 수 있습니다. 따라서 "fish & chips_are_great"는 _의 첫 번째 발생을 ¬로 대체하여 "fish & chips¬are_great"를 제공 한 다음 ¬로 분할하여 [ "fish & chips", "are_great"]
sebjwallace을 획득했습니다.

8

정규식을 다음과 같이 사용할 수 있습니다.

var arr = element.split(/_(.*)/)
분할 한계를 지정하는 두 번째 매개 변수를 사용할 수 있습니다. 즉 : var field = element.split ( '_', 1) [1];

6
분할 횟수가 아닌 리턴되는 분할 항목 수만 지정합니다. 'good_luck_buddy'.split('_', 1);그냥 반환['good']
Alex Vidal

그것에 대해 감사드립니다. 정규식을 사용하도록 게시물을 업데이트했습니다.
Chandu

(:?.*)비 캡처 그룹 있어야하는데? 그렇다면이어야 (?:.*)하지만 수정하면 더 이상 작동하지 않습니다. (:?.*)선택 사항과 일치 :하거나 0 개 이상의 문자를 찾습니다. 이 솔루션은 @MarkF와 같은 이유로 작동합니다. 첫 번째 이후의 모든 것이 _캡처 그룹에서 일치했기 때문에 토큰 목록에 추가됩니다. (또한, g수정자는 분할 정규식에서 사용될 때 영향을 미치지 않습니다.)
Alan Moore

고마워 몰랐어 정규식을 업데이트하고 몇 가지 시나리오를 시도했습니다 ...
Chandu

1
ie8에서는 작동하지 않으며 indexOf 및 하위 문자열로 다시 전환합니다.
Igor Alekseev

5

요즘 String.prototype.split에는 실제로 분할 수를 제한 할 수 있습니다.

str.split([separator[, limit]])

...

제한 옵션

스플릿 수를 제한하는 음이 아닌 정수입니다. 제공된 경우 지정된 구분 기호가 나타날 때마다 문자열을 분할하지만 한계 항목이 배열에 배치되면 중지됩니다. 남은 텍스트는 배열에 전혀 포함되지 않습니다.

한계에 도달하기 전에 문자열의 끝에 도달하면 배열에 한계보다 적은 항목이 포함될 수 있습니다. 한계가 0이면 분할이 수행되지 않습니다.

경고

예상대로 작동하지 않을 수 있습니다. 나는 나머지 구분 기호를 무시하기를 바랐지만 대신 한계에 도달하면 나머지 문자열을 다시 분할하여 반환 결과에서 분할 후 부분을 생략합니다.

let str = 'A_B_C_D_E'
const limit_2 = str.split('_', 2)
limit_2
(2) ["A", "B"]
const limit_3 = str.split('_', 3)
limit_3
(3) ["A", "B", "C"]

나는 바라고 있었다 :

let str = 'A_B_C_D_E'
const limit_2 = str.split('_', 2)
limit_2
(2) ["A", "B_C_D_E"]
const limit_3 = str.split('_', 3)
limit_3
(3) ["A", "B", "C_D_E"]

여기도 마찬가지입니다. PHP가 "first"와 "rest"로 분리 된 것 같습니다.
BananaAcid

5

이 솔루션은 저에게 효과적이었습니다.

var str = "good_luck_buddy";
var index = str.indexOf('_');
var arr = [str.slice(0, index), str.slice(index + 1)];

//arr[0] = "good"
//arr[1] = "luck_buddy"

또는

var str = "good_luck_buddy";
var index = str.indexOf('_');
var [first, second] = [str.slice(0, index), str.slice(index + 1)];

//first = "good"
//second = "luck_buddy"

그러나 스플리터의 문자가 두 개 이상인 경우에는 작동하지 않습니다.
haykam

4

String.split불행히도 Javascript 는 실제 분할 수를 제한 할 방법이 없습니다. 반환되는 실제 분할 항목 수를 지정하는 두 번째 인수가 있으므로 귀하의 경우에는 유용하지 않습니다. 해결책은 문자열을 분할하고 첫 번째 항목을 끈 다음 나머지 항목을 다시 결합하는 것입니다.

var element = $(this).attr('class');
var parts = element.split('_');

parts.shift(); // removes the first item from the array
var field = parts.join('_');

split 함수는 도움이되지 않지만 정규 표현식을 사용하면이를 달성하는 것 같습니다. 기본적으로 Split 함수 자체를 참조하도록 지정해야합니다.
Dan Hanly

1
흥미롭게도이 솔루션은 문제를보다 읽기 쉽고 관리하기 쉬운 솔루션으로 분류합니다. 필자의 이름을 첫 번째와 마지막으로 변환하는 경우 (이 요구 사항은이 논리를 강요했습니다)이 솔루션은 가장 잘 작동했으며 다른 솔루션보다 더 읽기 쉽습니다. 감사합니다
Sukima

이것은 더 이상 사실이 아닙니다 :)
Kraken

3

문자열의 두 부분이 필요하므로 정규식 lookbehind가 도움이됩니다.

const full_name = 'Maria do Bairro';
const [first_name, last_name] = full_name.split(/(?<=^[^ ]+) /);
console.log(first_name);
console.log(last_name);


3

할당을 해체하는 데 도움이 더 읽기 쉽습니다.

let [first, ...rest] = "good_luck_buddy".split('_')
rest = rest.join('_')

2

가장 빠른 솔루션?

나는 몇 가지 벤치 마크를 실행 했으며이 솔루션은 크게 승리했습니다. 1

str.slice(str.indexOf(delim) + delim.length)

// as function
function gobbleStart(str, delim) {
    return str.slice(str.indexOf(delim) + delim.length);
}

// as polyfill
String.prototype.gobbleStart = function(delim) {
    return this.slice(this.indexOf(delim) + delim.length);
};

다른 솔루션과의 성능 비교

유일하게 가까운 경쟁자는 substr대신 코드를 사용 하는 것을 제외하고는 동일한 코드 줄 이었습니다 slice.

내가 관련된 노력 다른 솔루션 split또는 RegExp의 큰 성능 저하를 가져다가 2 개에 대해 하였다 크기 순서 느린. 물론 join의 결과를 사용 split하면 추가 성능 저하가 추가됩니다.

왜 느려요? 새로운 객체 또는 배열을 만들 때마다 JS는 OS에서 메모리 청크를 요청해야합니다. 이 과정은 매우 느립니다.

벤치 마크를 쫓는 경우를위한 일반적인 지침은 다음과 같습니다.

  • 객체 {}나 어레이에 대한 새로운 동적 메모리 할당 []( split생성 하는 것과 같은 )은 많은 비용이 들게됩니다.
  • RegExp 검색은 문자열 검색보다 복잡하고 느립니다.
  • 이미 배열이있는 경우 배열을 파괴하는 것은 명시 적으로 색인을 생성하는 것만 큼 빠르며 멋지게 보입니다.

첫 번째 인스턴스를 넘어서 제거

다음은 n 번째 인스턴스까지 슬라이스하는 솔루션입니다. 빠르지는 않지만 OP의 질문에 따르면 gobble(element, '_', 1)여전히 a RegExp또는 split솔루션 보다 2 배 이상 빠르며 더 많은 작업을 수행 할 수 있습니다.

/*
`gobble`, given a positive, non-zero `limit`, deletes
characters from the beginning of `haystack` until `needle` has
been encountered and deleted `limit` times or no more instances
of `needle` exist; then it returns what remains. If `limit` is
zero or negative, delete from the beginning only until `-(limit)`
occurrences or less of `needle` remain.
*/
function gobble(haystack, needle, limit = 0) {
  let remain = limit;
  if (limit <= 0) { // set remain to count of delim - num to leave
    let i = 0;
    while (i < haystack.length) {
      const found = haystack.indexOf(needle, i);
      if (found === -1) {
        break;
      }
      remain++;
      i = found + needle.length;
    }
  }

  let i = 0;
  while (remain > 0) {
    const found = haystack.indexOf(needle, i);
    if (found === -1) {
      break;
    }
    remain--;
    i = found + needle.length;
  }
  return haystack.slice(i);
}

위의 정의로 gobble('path/to/file.txt', '/')파일 이름을 지정 gobble('prefix_category_item', '_', 1)하고이 답변의 첫 번째 솔루션과 같은 접두사를 제거합니다.


  1. 테스트는 macOSX 10.14의 Chrome 70.0.3538.110에서 실행되었습니다.

어서 ... 2019 년 ... 사람들이 아직도 이런 종류의 마이크로 벤치마킹을하고 있습니까?
Victor Schröder

나는 동의한다. 마이크로 벤치마킹은 약간 흥미롭지 만 최적화를 위해 컴파일러 나 번역기에 의존해야합니다. Mb 누군가 이것을 읽고 컴파일러를 빌드하거나 ejs / 내장을 사용하고 있으며 정규식을 사용할 수 없습니다. 그러나 이것은 정규 표현식보다 내 특정 사례에 더 좋습니다. ( "가장 빠른 해결책"을 제거하겠습니다)
TamusJRoyce

1

Mark F의 솔루션은 훌륭하지만 이전 브라우저에서는 지원되지 않습니다. Kennebec의 솔루션은 이전 브라우저에서 훌륭하고 지원되지만 정규식은 지원하지 않습니다.

따라서 문자열을 한 번만 분할하여 이전 브라우저에서 지원하고 정규식을 지원하는 솔루션을 찾고 있다면 여기 내 솔루션이 있습니다.

String.prototype.splitOnce = function(regex)
{
    var match = this.match(regex);
    if(match)
    {
        var match_i = this.indexOf(match[0]);
        
        return [this.substring(0, match_i),
        this.substring(match_i + match[0].length)];
    }
    else
    { return [this, ""]; }
}

var str = "something/////another thing///again";

alert(str.splitOnce(/\/+/)[1]);


1

정규 표현식에 익숙하지 않은 저와 같은 초보자에게는이 해결 방법이 효과적이었습니다.

   var field = "Good_Luck_Buddy";
   var newString = field.slice( field.indexOf("_")+1 );

slice () 메서드는 문자열의 일부를 추출하여 새 문자열을 반환하고 indexOf () 메서드는 문자열에서 지정된 값이 처음 발견 된 위치를 반환합니다.


이 문제를 해결하려면,하지만 그것을하는 적절한 방법이 아니다)
빅터 슈뢰더

1

정규식replace() 과 함께 문자열 메서드를 사용하십시오 .

var result = "good_luck_buddy".replace(/.*?_/, "");
console.log(result);

이 정규식은 전에 먼저 0 개 이상의 문자와 일치 _하고, _그 자체. 그런 다음 일치 항목이 빈 문자열로 바뀝니다.


document.body.innerHTML여기 부분은 완전히 쓸모입니다.
Victor Schröder

@ VictorSchröder 어떻게 스 니펫의 출력을 보지 document.body.innerHTML않겠습니까?
James T

1
document.body존재하는 DOM에 의존하며 순수한 JavaScript 환경에서는 작동하지 않습니다. console.log이 목적으로 충분하거나 단순히 검사 결과를 변수로 남겨 두십시오.
Victor Schröder

@ VictorSchröder 나는 그것이 많은 혼란을 초래했을 것이라고 생각하지는 않지만 그럼에도 불구하고 편집했습니다.
James T

0

이것은 Chrome + FF에서 나를 위해 일했습니다.

"foo=bar=beer".split(/^[^=]+=/)[1] // "bar=beer"
"foo==".split(/^[^=]+=/)[1] // "="
"foo=".split(/^[^=]+=/)[1] // ""
"foo".split(/^[^=]+=/)[1] // undefined

키가 필요한 경우 다음을 시도하십시오.

"foo=bar=beer".split(/^([^=]+)=/) // Array [ "", "foo", "bar=beer" ]
"foo==".split(/^([^=]+)=/) // [ "", "foo", "=" ]
"foo=".split(/^([^=]+)=/) // [ "", "foo", "" ]
"foo".split(/^([^=]+)=/) // [ "foo" ]

//[0] = ignored (holds the string when there's no =, empty otherwise)
//[1] = hold the key (if any)
//[2] = hold the value (if any)

0

트릭을 수행하는 하나의 RegExp이 있습니다.

'good_luck_buddy' . split(/^.*?_/)[1] 

먼저 '^'로 시작부터 일치를 시작합니다. 그런 다음 '_'이 아닌 모든 문자, 즉 첫 번째 '_'앞의 모든 문자와 일치합니다.

'?' 전체 패턴을 일치시키는 최소 문자 수는 '. *?' 그 뒤에 '_'가 오므로 마지막 문자로 경기에 포함됩니다.

따라서이 split ()은 일치하는 부분을 '스플리터'로 사용하여 결과에서 제거합니다. 따라서 첫 번째 '_'를 포함하여 모든 것을 제거하고 결과의 두 번째 요소로 나머지를 제공합니다. 첫 번째 요소는 일치하는 부분 앞의 부분을 나타내는 ""입니다. 경기는 처음부터 시작하기 때문에 ""입니다.

이전 답변에서 Chandu가 제공 한 /_(.*)/와 같이 작동하는 다른 RegExps가 있습니다.

/^.*?_/는 그룹이 replace ()를 사용하여 수행하는 특수 역할 캡처에 대해 알 필요없이 그 기능을 이해할 수 있다는 이점이 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.