캡처 한 그룹 만 바꾸는 방법?


196

문자열 전후에 HTML 코드가 있습니다.

name="some_text_0_some_text"

나는 다음과 같이 대체하고 0싶다 :!NEW_ID!

그래서 간단한 정규식을 만들었습니다.

.*name="\w+(\d+)\w+".*

그러나 독점적으로 캡처 된 블록을 바꾸는 방법을 모르겠습니다.

($ 1)과 같은 캡처 결과를 다른 문자열로 바꾸는 방법이 있습니까?

결과는 다음과 같습니다.

name="some_text_!NEW_ID!_some_text"

답변:


359

해결책은 이전 및 다음 텍스트에 대한 캡처를 추가하는 것입니다.

str.replace(/(.*name="\w+)(\d+)(\w+".*)/, "$1!NEW_ID!$3")

76
미래의 인사! 귀하의 솔루션은 정말 깔끔해 보입니다. 답을 설명해 주시겠습니까?
Polyducks

21
괄호는 "그룹"을 작성하는 데 사용되며, 1로 대체하여 액세스 할 수있는 base-1 인덱스를 지정 $하므로 첫 번째 단어 (\w+)는 그룹에 속하게되고 $1중간 부분 (\d+)은 두 번째 그룹이됩니다 (그러나 바꾸기에서 무시 됨) 세 번째 그룹은 $3입니다. 따라서 교체 문자열을 제공하면 "$1!new_ID!$3"$ 1 및 $ 3이 첫 번째 그룹 및 세 번째 그룹으로 자동 교체되어 두 번째 그룹을 새 문자열로 교체하여 텍스트를 유지합니다.
mix3d

4
나는 그것이 어떻게 작동하는지 이해하는 동안 더 우아한 솔루션을 원했습니다.>.
mix3d

9
1) \ d +를 캡처 할 필요조차 없습니다. 2) 왜 우아하지 않다고 말합니까? 캡처는 물건을 버리지 말고 보관하는 것입니다. 당신이 지키고 싶은 것은 AROUND \ d +입니다. 그래서이 주변 부분을 포착하는 것이 정말 합리적입니다.
Sir4ur0n

3
좋은 해결책. 캡처 그룹을 변환의 기초로 사용하여 캡처 그룹을 바꾸려면 어떻게해야합니까? 이를 수행하는 데 똑같이 우아한 해결책이 있습니까? 현재 내가 목록, 루프 그들에 캡처 그룹을 저장하고, 각 반복에서 변환 된 값을 캡처 그룹을 대체
수키

15

새로운 환경에서 Javascript는 ( ES2018 기준 ) 뒤쳐 졌으므로 이러한 상황에서 그룹을 완전히 피할 수 있습니다. 오히려, lookbehind 당신이 캡처 된 그룹 전에오고, 내다보기 위해 후 제공하고 교체하는 것에 대해 단지 !NEW_ID! :

const str = 'name="some_text_0_some_text"';
console.log(
  str.replace(/(?<=name="\w+)\d+(?=\w+")/, '!NEW_ID!')
);

이 방법을 사용하면 전체 일치 항목 교체해야합니다.

  • (?<=name="\w+)-Lookbehind for name"다음에 단어 문자가 있습니다 ( 행운 적으로 lookbehinds는 자바 스크립트에서 너비를 고정 할 필요가 없습니다!).
  • \d+ -하나 이상의 숫자와 일치-패턴의 유일한 부분은 둘러보기에없고 문자열의 유일한 부분은 결과와 일치합니다.
  • (?=\w+")-단어 문자에 대한 Lookahead 다음에 " `

뒤돌아보기는 새로운 것임을 명심하십시오. 최신 버전의 V8 (Chrome, Opera 및 Node 포함)에서는 작동하지만 다른 환경 에서는 아직까지는 그렇지 않습니다. 따라서 Node 및 자체 브라우저에서 lookbehind를 안정적으로 사용할 수 있지만 (최신 버전의 V8에서 실행되는 경우) 공용 클라이언트와 같이 임의의 클라이언트에서 아직 충분히 지원되지 않습니다.



그러나 예를 들어 숫자, 배수를 추출하고 "다시 입력"하려면 그룹화해야합니다 \d+.
Mosh Feu

@MoshFeu 대체 함수를 사용하고 전체 일치하는 숫자를 사용하십시오. 두 번째 매개 변수를로 바꾸십시오 match => match * 2. 숫자는 여전히 전체 일치하므로 그룹이 필요하지 않습니다
CertainPerformance

잡았다. 감사!
Mosh Feu

2

Matthew의 대답에 약간의 개선은 마지막 캡처 그룹 대신에 예견 일 수 있습니다.

.replace(/(\w+)(\d+)(?=\w+)/, "$1!NEW_ID!");

또는 십진수로 나누고 다음과 같이 새 ID와 결합 할 수 있습니다.

.split(/\d+/).join("!NEW_ID!");

예 / 벤치 마크 : https://codepen.io/jogai/full/oyNXBX


1

캡처 그룹 두 개도 가능했을 것입니다. 또한 숫자 앞뒤에 추가 왼쪽 및 오른쪽 경계로 두 개의 대시를 포함 시켰으며 수정 된 표현식은 다음과 같습니다.

(.*name=".+_)\d+(_[^"]+".*)

const regex = /(.*name=".+_)\d+(_[^"]+".*)/g;
const str = `some_data_before name="some_text_0_some_text" and then some_data after`;
const subst = `$1!NEW_ID!$2`;
const result = str.replace(regex, subst);
console.log(result);


표현식을 탐색 / 간단 화 / 수정하려는 경우 regex101.com의 오른쪽 상단에 설명되어 있습니다. 원하는 경우이 링크 에서 일부 샘플 입력과 어떻게 일치하는지 확인할 수도 있습니다.


정규식 회로

jex.im은 정규 표현식을 시각화합니다.

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


0

더 간단한 옵션은 숫자를 캡처하여 바꾸는 것입니다.

const name = 'preceding_text_0_following_text';
const matcher = /(\d+)/;

// Replace with whatever you would like
const newName = name.replace(matcher, 'NEW_STUFF');
console.log("Full replace", newName);

// Perform work on the match and replace using a function
// In this case increment it using an arrow function
const incrementedName = name.replace(matcher, (match) => ++match);
console.log("Increment", incrementedName);

자원

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