ProgramingTip

따옴표 안에 있지 않은 모든 인스턴스와 일치하는 정규식

bestdevel 2021. 1. 9. 16:25
반응형

따옴표 안에 있지 않은 모든 인스턴스와 일치하는 정규식


에서 이 Q / A는 , 주어진 정규 표현식 나는의 모든 인스턴스를 일치 여부 추론 하지 따옴표 안에 불가능하다. 즉, 이스케이프 된 따옴표 (예 :)와 일치 할 수 없습니다 "this whole \"match\" should be taken". 내가 모르는 방법이 내 문제를 해결할 것입니다.

그러나 그렇지 않다면 JavaScript에서 사용할 수있는 대안이 있는지 알고 싶습니다. 나는 대부분의 경우에 작동하는 우아한 솔루션을 제공하지 않습니다.

특히, .split () 및 .replace () 메서드로 작업 할 수있는 대안이 필요하지만 일반화 할 수있는 것이 가장 좋습니다.

예 :
입력 문자열 :
+bar+baz"not+or\"+or+\"this+"foo+bar+
+를 따옴표가 아닌 #으로 바꾸면 다음이 반환됩니다.
#bar#baz"not+or\"+or+\"this+"foo#bar#


모든 인스턴스는 따옴표 안에 있지 않은 정규식의 모든 인스턴스를 일치시킬 수 있습니다. 여기서 각 여는 따옴표는 다시 닫습니다. 위의 예에서와 같이 \+.

여기서 중요한 관찰은 단어 짝수 개의 따옴표가 있습니다. 이 미리보기 어설 션으로 모델링 할 수 있습니다.

\+(?=([^"]*"[^"]*")*[^"]*$)

이제 이스케이프 된 따옴표를 계산하지 않습니다. 이것은 조금 더 복잡해집니다. [^"]*다음 따옴표로 넘어가 는 대신 백 슬래시도 고려하고 [^"\\]*. 백 슬래시 또는 따옴표에 도달 한 후 백 슬래시가 발생하면 다음 문자를 무시하거나 이스케이프 처리되지 않은 다음 따옴표로 넘어갑니다. 처럼 보이네요 (\\.|"([^"\\]*\\.)*[^"\\]*"). 결합하면

\+(?=([^"\\]*(\\.|"([^"\\]*\\.)*[^"\\]*"))*[^"]*$)

나는 그것이 약간의 모호 라는 것을 인정합니다 . =)


Azmisov는이 질문을 부활 당신은 당신이 계획 any efficient alternative that could be used in JavaScript하고 말하고 때문에 any elegant solutions that would work in most, if not all, cases.

참조되지 않은 해결 방법이 있습니다.

대안과 쓸 때이 솔루션의 정규식은 놀랍도록 간단합니다.

"[^"]+"|(\+)

아이디어는 일치하지만 따옴표 안의 내용을 무시하여 해당 내용 (교대 왼쪽)을 무효화하는 것입니다. 오른쪽에서는 +그룹 1로 무력화되지 않은 모든 항목을 설치 하고 기능은 그룹 1을 검사합니다. 다음은 전체 작업 코드입니다.

<script>
var subject = '+bar+baz"not+these+"foo+bar+';
var regex = /"[^"]+"|(\+)/g;
replaced = subject.replace(regex, function(m, group1) {
    if (!group1) return m;
    else return "#";
});
document.write(replaced);

온라인 견본

동일한 원칙을 사용하여 일치 또는 분할 할 수 있습니다. 코드 샘플을 참조의 질문 및 가이드를 참조하십시오.

이것이 매우 일반적인 방법에 대한 다른 아이디어를 제공하기를 바랍니다. :)

빈 SDK는 어떻습니까?

위는 기술을 사용 설명서입니다. 정확한 필요에 따라 수 있습니다. 에 빈 문자열 텍스트이 포함되어있을 수 있다고 걱정되면 문자열 캡처 표현식 내의 수량 +자를에서 *다음으로 변경하십시오 .

"[^"]*"|(\+)

데모를 참조하십시오 .

이스케이프 된 따옴표는 어떻습니까?

다시 말하지만, 위는 기술을 마치 대답입니다. " 이 일치 무시 "을 필요에 정규식 맞게 조정할 수있을 뿐만 아니라 무시할 여러 표현식을 추가 할 수 있습니다. 예를 들어, 따옴표가 된 이스케이프 적절하게 무시 \\"|되도록하려면 이스케이프 된 큰 따옴표를 일치 여부 (및 무시) 위해 다른 두하기 개 앞에 대체 추가하여 시작할 수 있습니다 .

다음으로, "[^"]*"큰 따옴표로 묶인 문자열의 내용을 캡처 하는 섹션 내에서 이스케이프 된 큰 따옴표가 "닫는 센티널로 바뀌기 전에 일치하는지 확인하기 위해 대체를 추가 할 수 있습니다."(?:\\"|[^"])*"

결과 표현식에는 세 가지 분기가 있습니다.

  1. \\"일치하고 무시하다
  2. "(?:\\"|[^"])*"일치하고 무시하다
  3. (\+)일치, 캡처 및 처리

다른 정규식 버전에서는 lookbehind로이 작업을 더 쉽게 수행 할 수 있지만 JS는이를 지원하지 않습니다.

전체 정규식은 다음과 같습니다.

\\"|"(?:\\"|[^"])*"|(\+)

정규식 데모전체 스크립트를 참조하십시오 .

참고

  1. 상황 s1, s2, s3을 제외하고 패턴을 일치시키는 방법
  2. 패턴을 일치시키는 방법 ...

세 단계로 할 수 있습니다.

  1. 정규식 전역 대체를 사용하여 모든 문자열 본문 내용을 사이드 테이블로 추출합니다.
  2. 쉼표 번역 수행
  3. 정규식 전역 바꾸기를 사용하여 문자열 본문을 다시 바꿉니다.

아래 코드

// Step 1
var sideTable = [];
myString = myString.replace(
    /"(?:[^"\\]|\\.)*"/g,
    function (_) {
      var index = sideTable.length;
      sideTable[index] = _;
      return '"' + index + '"';
    });
// Step 2, replace commas with newlines
myString = myString.replace(/,/g, "\n");
// Step 3, swap the string bodies back
myString = myString.replace(/"(\d+)"/g,
    function (_, index) {
      return sideTable[index];
    });

설정 후 실행하면

myString = '{:a "ab,cd, efg", :b "ab,def, egf,", :c "Conjecture"}';

당신은 얻어야한다

{:a "ab,cd, efg"
 :b "ab,def, egf,"
 :c "Conjecture"}

1 단계 이후에

myString = '{:a "0", :b "1", :c "2"}'
sideTable = ["ab,cd, efg", "ab,def, egf,", "Conjecture"];

따라서 myString의 유일한 쉼표는 문자열 외부입니다. 2 단계 : 쉼표를 줄 바꿈으로 바꿉니다.

myString = '{:a "0"\n :b "1"\n :c "2"}'

마지막으로 숫자 만 포함 된 문자열을 원래 내용으로 바꿉니다.


zx81의 대답이 가장 성능이 좋고 깨끗한 대답 인 것처럼 보이지만 이스케이프 된 따옴표를 올바르게 잡으려면 다음 수정이 필요합니다.

var subject = '+bar+baz"not+or\\"+or+\\"this+"foo+bar+';

var regex = /"(?:[^"\\]|\\.)*"|(\+)/g;

또한 이미 언급 된 "group1 === undefined"또는 "! group1". 특히 2. 원래 질문에서 물었던 모든 것을 실제로 고려하는 것이 중요해 보입니다.

이 방법은 이스케이프되지 않은 따옴표 쌍 외부에 이스케이프 된 따옴표가없는 문자열을 암시 적으로 요구한다는 점을 언급해야합니다.

참조 URL : https://stackoverflow.com/questions/6462578/regex-to-match-all-instances-not-inside-quotes

반응형