Javascript에서 두 문자열 사이에 문자열을 가져 오는 정규식


166

나는 매우 비슷한 게시물을 찾았지만 여기서 정규 표현식을 얻을 수는 없습니다.

두 개의 다른 문자열 사이에있는 문자열을 반환하는 정규식을 작성하려고합니다. 예를 들어 : "cow"와 "milk"문자열 사이에있는 문자열을 원합니다.

내 암소는 항상 우유를 제공합니다

돌아올 것이다

"항상 제공"

지금까지 함께 정리 한 표현은 다음과 같습니다.

(?=cow).*(?=milk)

그러나 이것은 "cow always gives"라는 문자열을 반환합니다.


6
나는이 오래된 질문에 걸려서 왜 testRE가 배열인지 명확히하고 싶었습니다. test.match는 첫 번째 색인이 총 일치 항목 (즉, cow (. *) milk와 일치하는 문자열)으로 배열을 반환 한 다음 두 번째 괄호 세트가 있으면 (. *)와 같이 트랩 된 모든 문자열을 반환합니다. 그런 다음 testRE [2]
Salketer

4
줄 바꿈이 포함 된 문자열을 검색하는 경우이 솔루션이 작동하지 않습니다. 이 경우 "STRING_ONE ([\\ s \\ S] *?) STRING_TWO"를 사용해야합니다. stackoverflow.com/questions/22531252/…
Michael.Lumley

답변:


183

미리보기 (해당 (?=부분)는 입력을 소비하지 않습니다. 경계 검사 및 룩 백과 같이 0 인 어설 션 입니다.

cow부분 을 소비하기 위해 여기에서 규칙적인 일치를 원합니다 . 그 사이에 부분을 캡처하려면 캡처 그룹을 사용하십시오 (캡쳐하려는 패턴 부분을 괄호 안에 넣으십시오).

cow(.*)milk

예견이 전혀 필요하지 않습니다.


26
이것을 테스트 할 때 제공된 정규 표현식에 "cow"와 "milk"가 모두 포함됩니다.
TheCascadian

4
단계가 없습니다. 일치하는 결과를 얻으면 matched[1]전체 일치하는 텍스트가 아닌가있는 첫 번째 캡처 그룹의 일치하는 텍스트를 추출해야합니다 matched[0].
Rory O'Kane

7
Javascript에서는 실제로 ([\s\S]*?)보다는 을 사용해야 (.*?)합니다.
Qian Chen

7
이 유용한 techique이지만 이럴이 질문에 대한 정답이 아니기 때문에, 그것은이 "소"와 "우유"를 포함하기 때문에 @TheCascadian에 의해 명시된 바와 같이,을 downvoted했다
알미르 캄포스

@AlmirCampos-내가 실수하지 않으면 "cow"와 "milk"와 일치하지 않고이 일치를 수행 할 수있는 방법이 없습니다 (두 가지 사이에있는 것을 일치시키고 싶기 때문에). 문제는 RegEx 자체가 아니라 나중에 Rory O'Kane이 언급 한대로 처리하는 방법에 있습니다. 그렇지 않으면 주변 공간과 만 일치 할 수 있으며 매우 잘못된 반환을 제공합니까?
태어남

69

JavaScript에서 두 문자열 사이에 문자열을 가져 오는 정규식

대부분의 경우에 작동하는 가장 완벽한 솔루션 은 지연 도트 매칭 패턴이 있는 캡처 그룹 을 사용 하는 것입니다 . 그러나 .JavaScript 정규식 의 점 은 줄 바꿈 문자와 일치하지 않으므로 100 %의 경우 작동하는 것은 [^]또는 [\s\S]/ [\d\D]/ [\w\W]구문입니다.

ECMAScript 2018 및 최신 호환 솔루션

ECMAScript 2018을 지원하는 JavaScript 환경 에서 s수정자는 .줄 바꿈 문자를 포함한 모든 문자를 일치 시킬 수 있으며 정규식 엔진은 가변 길이의 lookbehinds를 지원합니다. 따라서 정규 표현식을 사용할 수 있습니다

var result = s.match(/(?<=cow\s+).*?(?=\s+milk)/gs); // Returns multiple matches if any
// Or
var result = s.match(/(?<=cow\s*).*?(?=\s*milk)/gs); // Same but whitespaces are optional

두 경우 모두에서, 현재 위치에 대한 판정 cow후 임의 1/0 이상의 공백으로 cow그리고, 가능한 한 적은 수의 일치 및 소비 (= 매치 값에 첨가)되는 것에 따라 임의 0+ 문자를, 그리고 milk어떤과 (검사되고 이 부분 문자열 앞의 1/0 이상의 공백).

시나리오 1 : 단일 라인 입력

이 시나리오와 아래의 다른 모든 시나리오는 모든 JavaScript 환경에서 지원됩니다. 답변 맨 아래에있는 사용 예를 참조하십시오.

cow (.*?) milk

cow먼저 공간을 찾은 다음, 줄 바꿈 문자 이외의 0+ 문자는 가능한 한 적은 *?게으른 수량 자로 그룹 1에 캡처 된 다음 공백이 milk따라야합니다 (및 일치하고 소비 됨 ). ).

시나리오 2 : 여러 줄 입력

cow ([\s\S]*?) milk

여기서 cow공백이 먼저 일치하면 가능한 한 적은 수의 0+ 문자가 일치하여 그룹 1에 캡처 된 다음 공백 milk이 일치됩니다.

시나리오 3 : 겹치는 일치

같은 문자열을 가지고 있고 + + 와 >>>15 text>>>67 text2>>>사이에 2 개의 일치 항목 을 가져와야하는 경우 첫 번째 일치 항목을 찾을 때 이전 이 이미 소비 되었기 때문에 1 개의 일치 항목 만 찾을 수 있으므로 사용할 수 없습니다 . 긍정적 인 미리보기 를 사용 하여 텍스트를 실제로 "고글 링"하지 않고 (예 : 일치 항목을 추가하지 않고) 텍스트 존재를 확인할 수 있습니다 .>>>numberwhitespace>>>/>>>\d+\s(.*?)>>>/g>>>67

/>>>\d+\s(.*?)(?=>>>)/g

참고 항목 온라인 정규식 데모가 항복 text1하고 text2그룹으로 한 내용이 발견했다.

또한 문자열에 대해 가능한 모든 겹치는 일치를 얻는 방법을 참조하십시오 .

성능 고려 사항

.*?매우 긴 입력이 주어지면 정규식 패턴 내부의 게으른 점 일치 패턴 ( )이 스크립트 실행 속도를 늦출 수 있습니다. 대부분의 경우 루프 풀기 기술 이 더 큰 도움이됩니다. 사이 cowmilk에서 모두를 얻으려고하면로 "Their\ncow\ngives\nmore\nmilk"시작하지 않는 모든 줄을 일치시켜야 milk하므로 대신 다음을 cow\n([\s\S]*?)\nmilk사용할 수 있습니다.

/cow\n(.*(?:\n(?!milk$).*)*)\nmilk/gm

정규식 데모를 참조하십시오 (있는 경우 \r\n사용 /cow\r?\n(.*(?:\r?\n(?!milk$).*)*)\r?\nmilk/gm). 이 작은 테스트 문자열을 사용하면 성능 향상은 무시할 수 있지만 텍스트가 매우 크면 차이가 느껴집니다 (특히 줄이 길고 줄 바꿈이 많지 않은 경우).

JavaScript에서 샘플 정규식 사용법 :

//Single/First match expected: use no global modifier and access match[1]
console.log("My cow always gives milk".match(/cow (.*?) milk/)[1]);
// Multiple matches: get multiple matches with a global modifier and
// trim the results if length of leading/trailing delimiters is known
var s = "My cow always gives milk, thier cow also gives milk";
console.log(s.match(/cow (.*?) milk/g).map(function(x) {return x.substr(4,x.length-9);}));
//or use RegExp#exec inside a loop to collect all the Group 1 contents
var result = [], m, rx = /cow (.*?) milk/g;
while ((m=rx.exec(s)) !== null) {
  result.push(m[1]);
}
console.log(result);

현대적인 String#matchAll방법 사용

const s = "My cow always gives milk, thier cow also gives milk";
const matches = s.matchAll(/cow (.*?) milk/g);
console.log(Array.from(matches, x => x[1]));


51

여기에 젖소와 우유 사이에 무엇이 있는지 알아내는 정규식이 있습니다 (선행 / 후행 공간 없음).

srctext = "My cow always gives milk.";
var re = /(.*cow\s+)(.*)(\s+milk.*)/;
var newtext = srctext.replace(re, "$2");

예 : http://jsfiddle.net/entropo/tkP74/


17
  • 당신은 캡처해야 .*
  • 당신은 .*욕심을 만들 수 있습니다 (그러나 꼭 그런 것은 아닙니다)
  • 예견 할 필요는 없습니다.

    > /cow(.*?)milk/i.exec('My cow always gives milk');
    ["cow always gives milk", " always gives "]

이 특별한 경우에, 욕심이 많으면 말미암아 끝까지 후진 할 것입니다 (아마도).
Ben

9

선택한 답변이 저에게 효과가 없었습니다 ... 음 ...

"항상 제공"의 공간을 정리하기 위해 젖소 및 / 또는 우유 전에 공간을 추가하기 만하면됩니다.

/(?<=cow ).*(?= milk)/

여기에 이미지 설명을 입력하십시오


당신은 당신의 자신의 답변에 댓글을 달 필요가 없습니다, 그냥 편집하십시오.
Cody G

Look Behind ?<=는 Javascript에서 지원되지 않습니다.
마크 카펜터 주니어

당신은을 통해 그것을 테스트하는 경우 @MarkCarpenterJr regextester.com , 그 힌트를 얻을 것이다. 사이트가 이전 사양의 규칙을 기반으로 한 것 같습니다. Lookbehind가 지원됩니다. stackoverflow.com/questions/30118815/…를 참조하십시오. 이 패턴은 최신 브라우저에서 오류없이 잘 작동합니다. 대신이 검사기를 사용해보십시오 regex101.com
duduwe

@ CodyG.ah 예. 알았다.
duduwe

8

아래 Martinho Fernandes의 솔루션을 사용하여 필요한 것을 얻을 수있었습니다. 코드는 다음과 같습니다

var test = "My cow always gives milk";

var testRE = test.match("cow(.*)milk");
alert(testRE[1]);

testRE 변수를 배열로 경고하고 있음을 알 수 있습니다. 어떤 이유로 testRE가 배열로 반환되기 때문입니다. 출력 :

My cow always gives milk

로 변경 :

always gives

1
고마워, 나는 그것을 위해 바이올린 ( jsfiddle.net/MoscaPt/g5Lngjx8/2 )을 추가했습니다. / Johan
Mosca Pt

4

다음 정규식을 사용하십시오.

(?<=My cow\s).*?(?=\smilk)

Look Behind ?<=는 Javascript에서 지원되지 않습니다. 그래도 방법이 될 것입니다.
마크 카펜터 주니어

JavaScript로 지원됩니다. Safari 및 Mozilla (아직)에서는 지원되지 않으며 Chrome 및 Opera에서만 지원됩니다.
Paul Strupeikis

3

구문이 주어진 정규 표현식은 지루하고 시간 소모적입니다. 이미 자바 스크립트를 사용하고 있기 때문에 정규 표현식없이 다음을 수행하는 것이 더 쉽습니다.

const text = 'My cow always gives milk'
const start = `cow`;
const end = `milk`;
const middleText = text.split(start)[1].split(end)[0]
console.log(middleText) // prints "always gives"

2
나를 위해 작동합니다! 정말 간단하기 때문에 환상적인 답변입니다! :)
Andrew Irwin


0

match () 메서드는 문자열에서 일치하는 항목을 검색하고 Array 객체를 반환합니다.

// Original string
var str = "My cow always gives milk";

// Using index [0] would return<br/>
// "**cow always gives milk**"
str.match(/cow(.*)milk/)**[0]**


// Using index **[1]** would return
// "**always gives**"
str.match(/cow(.*)milk/)[1]

0

직무

두 문자열 사이의 부분 문자열 추출 (이 두 문자열 제외)

해결책

let allText = "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum";
let textBefore = "five centuries,";
let textAfter = "electronic typesetting";
var regExp = new RegExp(`(?<=${textBefore}\\s)(.+?)(?=\\s+${textAfter})`, "g");
var results = regExp.exec(allText);
if (results && results.length > 1) {
    console.log(results[0]);
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.