질문자 :nickf
정규 표현식을 사용하여 문자열의 일부를 일치시킨 다음 괄호로 묶인 하위 문자열에 액세스하고 싶습니다.
var myString = "something format_abc"; // I want "abc" var arr = /(?:^|\s)format_(.*?)(?:\s|$)/.exec(myString); console.log(arr); // Prints: [" format_abc", "abc"] .. so far so good. console.log(arr[1]); // Prints: undefined (???) console.log(arr[0]); // Prints: format_undefined (!!!)
내가 무엇을 잘못하고 있지?
나는 위의 정규식 코드에 아무런 문제가 없다는 것을 발견했습니다. 내가 테스트한 실제 문자열은 다음과 같습니다.
"date format_%A"
"%A"가 정의되지 않았다고 보고하는 것은 매우 이상한 동작으로 보이지만 이 질문과 직접적으로 관련이 없기 때문에 새 질문을 열었습니다 . 일치하는 하위 문자열이 JavaScript에서 "undefined"를 반환하는 이유는 무엇입니까? .
문제는 console.log
printf
문과 같은 매개변수를 취하고 내가 로깅하고 있던 문자열( "%A"
)이 특별한 값을 가지고 있기 때문에 다음 매개변수의 값을 찾으려는 것이었습니다.
다음과 같이 캡처 그룹에 액세스할 수 있습니다.
var myString = "something format_abc"; var myRegexp = /(?:^|\s)format_(.*?)(?:\s|$)/g; var myRegexp = new RegExp("(?:^|\s)format_(.*?)(?:\s|$)", "g"); var match = myRegexp.exec(myString); console.log(match[1]); // abc
일치하는 항목이 여러 개인 경우 반복할 수 있습니다.
var myString = "something format_abc"; var myRegexp = new RegExp("(?:^|\s)format_(.*?)(?:\s|$)", "g"); match = myRegexp.exec(myString); while (match != null) { // matched text: match[0] // match start: match.index // capturing group n: match[n] console.log(match[0]) match = myRegexp.exec(myString); }
편집: 2019-09-10
보시다시피 여러 경기를 반복하는 방법은 그리 직관적이지 않았습니다. String.prototype.matchAll
메소드의 제안으로 이어집니다. 이 새로운 방법은 ECMAScript 2020 사양에 포함될 예정 입니다. 깨끗한 API를 제공하고 여러 문제를 해결합니다. Chrome 73+ / Node 12+ 및 Firefox 67+와 같은 주요 브라우저 및 JS 엔진에 상륙하기 시작했습니다.
이 메서드는 반복자를 반환하고 다음과 같이 사용됩니다.
const string = "something format_abc"; const regexp = /(?:^|\s)format_(.*?)(?:\s|$)/g; const matches = string.matchAll(regexp); for (const match of matches) { console.log(match); console.log(match.index) }
iterator를 반환하기 때문에 게으르다고 말할 수 있습니다. 이것은 특히 많은 수의 캡처링 그룹이나 매우 큰 문자열을 처리할 때 유용합니다. 그러나 필요한 경우 스프레드 구문 또는 Array.from
메서드를 사용하여 결과를 Array로 쉽게 변환할 수 있습니다.
function getFirstGroup(regexp, str) { const array = [...str.matchAll(regexp)]; return array.map(m => m[1]); } // or: function getFirstGroup(regexp, str) { return Array.from(str.matchAll(regexp), m => m[1]); }
그동안 이 제안이 더 폭넓은 지지를 받는 동안 공식 shim 패키지를 사용할 수 있습니다.
또한 이 방법의 내부 작동은 간단합니다. 제너레이터 함수를 사용하는 동등한 구현은 다음과 같습니다.
function* matchAll(str, regexp) { const flags = regexp.global ? regexp.flags : regexp.flags + "g"; const re = new RegExp(regexp, flags); let match; while (match = re.exec(str)) { yield match; } }
원본 regexp의 복사본이 생성됩니다. 이는 다중 일치를 수행할 때 lastIndex
속성의 변형으로 인한 부작용을 피하기 위한 것입니다.
또한 무한 루프를 피하기 위해 정규 표현식에 전역 플래그가 있는지 확인해야 합니다.
또한 이 StackOverflow 질문도 제안 논의 에서 언급된 것을 알게 되어 기쁩니다.
Christian C. Salvadó다음은 각 일치 항목에 대해 n 번째 캡처 그룹을 가져오는 데 사용할 수 있는 방법입니다.
function getMatches(string, regex, index) { index || (index = 1); // default to the first capturing group var matches = []; var match; while (match = regex.exec(string)) { matches.push(match[index]); } return matches; } // Example : var myString = 'something format_abc something format_def something format_ghi'; var myRegEx = /(?:^|\s)format_(.*?)(?:\s|$)/g; // Get an array containing the first capturing group for every match var matches = getMatches(myString, myRegEx, 1); // Log results document.write(matches.length + ' matches found: ' + JSON.stringify(matches)) console.log(matches);
Mathias Bynens var myString = "something format_abc"; var arr = myString.match(/\bformat_(.*?)\b/); console.log(arr[0] + " " + arr[1]);
\b
는 정확히 같은 것이 아닙니다. ( --format_foo/
format_a_b
에서는 작동하지 않습니다.) 하지만 귀하의 표현에 대한 대안을 보여주고 싶었습니다. 괜찮습니다. 물론 match
콜이 중요하다.
PhiLho마지막으로 나에게 잘 맞는 한 줄의 코드를 찾았습니다(JS ES6).
let reg = /#([\S]+)/igm; // Get hashtags. let string = 'mi alegría es total! \n#fiestasdefindeaño #PadreHijo #buenosmomentos #france #paris'; let matches = (string.match(reg) || []).map(e => e.replace(reg, '$1')); console.log(matches);
그러면 다음이 반환됩니다.
['fiestasdefindeaño', 'PadreHijo', 'buenosmomentos', 'france', 'paris']
Sebastien H.위의 다중 일치 괄호 예와 관련하여 원하는 것을 얻지 못한 후 여기에서 답변을 찾고 있었습니다.
var matches = mystring.match(/(?:neededToMatchButNotWantedInResult)(matchWanted)/igm);
위의 while 및 .push()를 사용하여 약간 복잡한 함수 호출을 살펴본 후 mystring.replace() 대신 문제를 매우 우아하게 해결할 수 있다는 것을 깨달았습니다(교체는 요점이 아니며 완료되지도 않았습니다. , 두 번째 매개변수에 대한 CLEAN 내장 재귀 함수 호출 옵션은 다음과 같습니다.):
var yourstring = 'something format_abc something format_def something format_ghi'; var matches = []; yourstring.replace(/format_([^\s]+)/igm, function(m, p1){ matches.push(p1); } );
그 후에는 다시는 .match()를 거의 사용하지 않을 것입니다.
AlexzString#matchAll
( 3단계 초안/2018년 12월 7일 제안 참조 )은 일치 개체의 모든 그룹에 대한 액세스를 단순화합니다(그룹 0은 전체 일치이고 추가 그룹은 패턴의 캡처 그룹에 해당함).
matchAll
/g
를 사용하여 while
루프와 exec
를 피할 수 있습니다 matchAll
for...of
, array spread 또는 Array.from()
과 함께 사용할 수 있는 반복자를 다시 얻을 수 있습니다. Array.from()
구성
이 방법은 유사한 출력 산출 Regex.Matches
C에서 #, re.finditer
, 파이썬을 preg_match_all
PHP있다.
JS 데모 보기(Google Chrome 73.0.3683.67(공식 빌드), 베타(64비트)에서 테스트됨):
var myString = "key1:value1, key2-value2!!@key3=value3"; var matches = myString.matchAll(/(\w+)[:=-](\w+)/g); console.log([...matches]); // All match with capturing group values
console.log([...matches])
표시
다음을 사용하여 일치 값 또는 특정 그룹 값을 얻을 수도 있습니다.
let matchData = "key1:value1, key2-value2!!@key3=value3".matchAll(/(\w+)[:=-](\w+)/g) var matches = [...matchData]; // Note matchAll result is not re-iterable console.log(Array.from(matches, m => m[0])); // All match (Group 0) values // => [ "key1:value1", "key2-value2", "key3=value3" ] console.log(Array.from(matches, m => m[1])); // All match (Group 1) values // => [ "key1", "key2", "key3" ]
참고 : 브라우저 호환성 세부 정보를 참조하십시오.
Wiktor Stribiżew이 답변에 사용된 용어:
- 일치 는 다음과 같이 문자열에 대해 RegEx 패턴을 실행한 결과를 나타냅니다.
someString.match(regexPattern)
. - 일치하는 패턴 은 모두 일치 배열 내에 있는 입력 문자열의 일치하는 모든 부분을 나타냅니다. 이들은 모두 입력 문자열 안에 있는 패턴의 인스턴스입니다.
- 일치하는 그룹 은 RegEx 패턴에 정의된 catch할 모든 그룹을 나타냅니다. (괄호 안의 패턴, 예:
/format_(.*?)/g
, 여기서 (.*?)
는 일치하는 그룹이 됩니다.) 이것은 일치하는 패턴 내에 있습니다.
설명
일치하는 그룹에 액세스하려면 일치하는 각 패턴 에서 일치 항목 을 반복하는 함수 또는 유사한 것이 필요합니다. 다른 답변에서 볼 수 있듯이 이를 수행할 수 있는 여러 가지 방법이 있습니다. 대부분의 다른 답변은 while 루프를 사용하여 일치하는 모든 패턴을 반복하지만 우리 모두는 해당 접근 방식의 잠재적 위험을 알고 있다고 생각합니다. 주석에서만 언급된 패턴 자체가 아니라 new RegExp()
와 일치해야 합니다. 이는 .exec()
메서드가 제너레이터 함수 와 유사하게 동작하기 때문입니다. 일치 항목이 있을 때마다 중지 .exec()
.lastIndex
를 계속 유지하기 때문입니다.
코드 예제
다음은 일치하는 모든 Array
을 반환하는 searchString
함수의 예입니다. 여기서 각 match
는 모든 일치하는 그룹 이 포함 Array
입니다. for
Array.prototype.map()
함수와 보다 성능이 뛰어난 방법을 모두 사용하는 예제를 제공했습니다.
간결한 버전(더 적은 코드, 더 많은 구문 설탕)
이들은 더 빠른 for
forEach
루프를 구현하기 때문에 성능이 떨어집니다.
// Concise ES6/ES2015 syntax const searchString = (string, pattern) => string .match(new RegExp(pattern.source, pattern.flags)) .map(match => new RegExp(pattern.source, pattern.flags) .exec(match)); // Or if you will, with ES5 syntax function searchString(string, pattern) { return string .match(new RegExp(pattern.source, pattern.flags)) .map(match => new RegExp(pattern.source, pattern.flags) .exec(match)); } let string = "something format_abc", pattern = /(?:^|\s)format_(.*?)(?:\s|$)/; let result = searchString(string, pattern); // [[" format_abc", "abc"], null] // The trailing `null` disappears if you add the `global` flag
고성능 버전(더 많은 코드, 더 적은 구문 설탕)
// Performant ES6/ES2015 syntax const searchString = (string, pattern) => { let result = []; const matches = string.match(new RegExp(pattern.source, pattern.flags)); for (let i = 0; i < matches.length; i++) { result.push(new RegExp(pattern.source, pattern.flags).exec(matches[i])); } return result; }; // Same thing, but with ES5 syntax function searchString(string, pattern) { var result = []; var matches = string.match(new RegExp(pattern.source, pattern.flags)); for (var i = 0; i < matches.length; i++) { result.push(new RegExp(pattern.source, pattern.flags).exec(matches[i])); } return result; } let string = "something format_abc", pattern = /(?:^|\s)format_(.*?)(?:\s|$)/; let result = searchString(string, pattern); // [[" format_abc", "abc"], null] // The trailing `null` disappears if you add the `global` flag
나는 이러한 대안을 다른 답변에서 이전에 언급한 대안과 아직 비교하지 않았지만 이 접근 방식이 다른 것보다 성능이 떨어지고 안전하지 않은지 의심스럽습니다.
Daniel Hallgren귀하의 구문은 아마도 유지하기에 가장 좋지 않을 것입니다. FF/Gecko는 RegExp를 Function의 확장으로 정의합니다.
(FF2는 typeof(/pattern/) == 'function'
까지 갔다)
이것은 FF에만 해당되는 것 같습니다. IE, Opera 및 Chrome은 모두 예외를 던집니다.
대신 이전에 다른 사람들이 언급한 RegExp#exec
또는 String#match
.
동일한 결과를 제공합니다.
var regex = /(?:^|\s)format_(.*?)(?:\s|$)/; var input = "something format_abc"; regex(input); //=> [" format_abc", "abc"] regex.exec(input); //=> [" format_abc", "abc"] input.match(regex); //=> [" format_abc", "abc"]
Jonathan Lonowskiexec
메소드를 호출할 필요가 없습니다! 문자열에서 직접 "일치" 메서드를 사용할 수 있습니다. 괄호만 잊지 마세요.
var str = "This is cool"; var matches = str.match(/(This is)( cool)$/); console.log( JSON.stringify(matches) ); // will print ["This is cool","This is"," cool"] or something like that...
위치 0에는 모든 결과가 포함된 문자열이 있습니다. 위치 1에는 괄호로 표시된 첫 번째 일치 항목이 있고, 위치 2에는 괄호 안에 분리된 두 번째 일치 항목이 있습니다. 중첩된 괄호는 까다로우므로 주의하십시오!
Andre Carneiro한 쌍의 괄호가 있는 경우에만 실용적인 하나의 라이너:
while ( ( match = myRegex.exec( myStr ) ) && matches.push( match[1] ) ) {};
Nabil Kadimies2018을 사용하면 이제 String.match()
를 사용할 수 있으며 정규식에서 수행하려는 작업을 보다 명시적으로 만들 수 있습니다.
const url = 'https://stackoverflow.com/questions/432493/how-do-you-access-the-matched-groups-in-a-javascript-regular-expression?some=parameter'; const regex = /(?<protocol>https?):\/\/(?<hostname>[\w-\.]*)\/(?<pathname>[\w-\./]+)\??(?<querystring>.*?)?$/; const { groups: segments } = url.match(regex); console.log(segments);
그리고 당신은 같은 것을 얻을 것이다
{프로토콜: "https", 호스트 이름: "stackoverflow.com", 경로 이름: "questions/432493/how-do-you-access-the-matched-groups-in-a-javascript-regular-expression", 쿼리 문자열: " 일부=매개변수"}
David Cheung코드 사용:
console.log(arr[1]); // prints: abc console.log(arr[0]); // prints: format_abc
편집: 중요한 경우 Safari 3.
eyelidlessness function getMatches(string, regex, index) { index || (index = 1); // default to the first capturing group var matches = []; var match; while (match = regex.exec(string)) { matches.push(match[index]); } return matches; } // Example : var myString = 'Rs.200 is Debited to A/c ...2031 on 02-12-14 20:05:49 (Clear Bal Rs.66248.77) AT ATM. TollFree 1800223344 18001024455 (6am-10pm)'; var myRegEx = /clear bal.+?(\d+\.?\d{2})/gi; // Get an array containing the first capturing group for every match var matches = getMatches(myString, myRegEx, 1); // Log results document.write(matches.length + ' matches found: ' + JSON.stringify(matches)) console.log(matches);
function getMatches(string, regex, index) { index || (index = 1); // default to the first capturing group var matches = []; var match; while (match = regex.exec(string)) { matches.push(match[index]); } return matches; } // Example : var myString = 'something format_abc something format_def something format_ghi'; var myRegEx = /(?:^|\s)format_(.*?)(?:\s|$)/g; // Get an array containing the first capturing group for every match var matches = getMatches(myString, myRegEx, 1); // Log results document.write(matches.length + ' matches found: ' + JSON.stringify(matches)) console.log(matches);
Jack정규식이 다음 과 같아야 한다는 PhiLo에 동의하더라도 귀하의 코드는 저에게 적합합니다(Mac의 경우 FF3).
/\bformat_(.*?)\b/
(물론 정규식의 문맥을 모르기 때문에 확실하지 않습니다.)
PEZ/*Regex function for extracting object from "window.location.search" string. */ var search = "?a=3&b=4&c=7"; // Example search string var getSearchObj = function (searchString) { var match, key, value, obj = {}; var pattern = /(\w+)=(\w+)/g; var search = searchString.substr(1); // Remove '?' while (match = pattern.exec(search)) { obj[match[0].split('=')[0]] = match[0].split('=')[1]; } return obj; }; console.log(getSearchObj(search));
Pawel Kwiecien여러 일치 항목을 구문 분석하기 위해 명시적 루프가 실제로 필요하지 않습니다. String.prototype.replace(regex, func)
설명된 대로 두 번째 인수로 대체 함수를 전달합니다.
var str = "Our chief weapon is {1}, {0} and {2}!"; var params= ['surprise', 'fear', 'ruthless efficiency']; var patt = /{([^}]+)}/g; str=str.replace(patt, function(m0, m1, position){return params[parseInt(m1)];}); document.write(str);
m0
인수는 전체 일치 하위 문자열 {0}
, {1}
등을 m1
은 첫 번째 일치 그룹, 즉 첫 번째 일치의 경우 0
정규식에서 대괄호로 묶인 부분을 나타냅니다. 그리고 position
은 일치하는 그룹이 발견된 문자열 내의 시작 인덱스입니다. 이 경우에는 사용되지 않습니다.
ccpizza백슬래시 다음에 일치하는 그룹의 번호를 사용하여 정규식에서 일치하는 그룹에 액세스할 수 있습니다.
/([az])\1/
첫 번째 그룹([az])과 일치하는 코드 \1에서
Md. A. Barik한 줄 솔루션:
const matches = (text,regex) => [...text.matchAll(regex)].map(([match])=>match)
따라서 다음과 같이 사용할 수 있습니다(/g를 사용해야 함).
matches("something format_abc", /(?:^|\s)format_(.*?)(?:\s|$)/g)
결과:
[" format_abc"]
Caio Santos@cms가 ECMAScript(ECMA-262)에서 matchAll
을 사용할 수 있습니다. 반복자를 반환하고 [... ]
(확산 연산자)에 넣으면 배열로 변환됩니다.(이 정규식은 파일 이름의 URL을 추출합니다.)
let text = `<a href="http://myhost.com/myfile_01.mp4">File1</a> <a href="http://myhost.com/myfile_02.mp4">File2</a>`; let fileUrls = [...text.matchAll(/href="(http\:\/\/[^"]+\.\w{3})\"/g)].map(r => r[1]); console.log(fileUrls);
MSS모든 그룹 발생 가져오기
let m=[], s = "something format_abc format_def format_ghi"; s.replace(/(?:^|\s)format_(.*?)(?:\s|$)/g, (x,y)=> m.push(y)); console.log(m);
Kamil Kiełczewski나는 당신이 나와 같으며 정규식이 다음과 같은 객체를 반환하기를 바랍니다.
{ match: '...', matchAtIndex: 0, capturedGroups: [ '...', '...' ] }
그런 다음 아래에서 기능을 잘라냅니다.
/** * @param {string | number} input * The input string to match * @param {regex | string} expression * Regular expression * @param {string} flags * Optional Flags * * @returns {array} * [{ match: '...', matchAtIndex: 0, capturedGroups: [ '...', '...' ] }] */ function regexMatch(input, expression, flags = "g") { let regex = expression instanceof RegExp ? expression : new RegExp(expression, flags) let matches = input.matchAll(regex) matches = [...matches] return matches.map(item => { return { match: item[0], matchAtIndex: item.index, capturedGroups: item.length > 1 ? item.slice(1) : undefined } }) } let input = "key1:value1, key2:value2 " let regex = /(\w+):(\w+)/g let matches = regexMatch(input, regex) console.log(matches)
DelconRegExp.$1...$n 번째 그룹을 사용하십시오. 예:
1.첫 번째 그룹 RegExp와 일치시키려면 $1
- 두 번째 그룹 RegExp.$2와 일치시키려면
regex likey에서 3개의 그룹을 사용하는 경우(string.match(regex) 이후에 사용 참고)
정규식.$1 정규식.$2 정규식.$3
var str = "The rain in ${india} stays safe"; var res = str.match(/\${(.*?)\}/ig); //i used only one group in above example so RegExp.$1 console.log(RegExp.$1)
//easiest way is use RegExp.$1 1st group in regex and 2nd grounp like //RegExp.$2 if exist use after match var regex=/\${(.*?)\}/ig; var str = "The rain in ${SPAIN} stays ${mainly} in the plain"; var res = str.match(regex); for (const match of res) { var res = match.match(regex); console.log(match); console.log(RegExp.$1) }
ßãlãjî나는 당신이 abc 하위 문자열을 포함하는 모든 단어를 잡고 일치하는 그룹/항목을 저장 하기를 원한다고 생각하여 다음 스크립트를 만들었습니다.
s = 'something format_abc another word abc abc_somestring' console.log(s.match(/\b\w*abc\w*\b/igm));
-
\b
- 단어 경계 -
\w*
- 0개 이상의 단어 문자 -
abc
- 정확히 일치 -
\w*
- 0개 이상의 단어 문자 -
\b
- 단어 경계
참조: 정규식: https://javascript.info/regexp-introduction 이라는 단어가 포함된 모든 단어와 일치
Glorified출처 : http:www.stackoverflow.com/questions/432493/how-do-you-access-the-matched-groups-in-a-javascript-regular-expression