" It's big \"problem "
정규식을 사용 하여 하위 문자열 을 어떻게 얻 습니까?
s = ' function(){ return " It\'s big \"problem "; }';
" It's big \"problem "
정규식을 사용 하여 하위 문자열 을 어떻게 얻 습니까?
s = ' function(){ return " It\'s big \"problem "; }';
답변:
/"(?:[^"\\]|\\.)*"/
Regex Coach 및 PCRE Workbench에서 작동합니다.
자바 스크립트 테스트 예 :
var s = ' function(){ return " Is big \\"problem\\", \\no? "; }';
var m = s.match(/"(?:[^"\\]|\\.)*"/);
if (m != null)
alert(m);
(?:...)
는 수동적이거나 캡처하지 않는 그룹입니다. 나중에 역 참조 할 수 없음을 의미합니다.
/(["'])(?:[^\1\\]|\\.)*?\1/
var s = ' my \\"new\\" string and \"this should be matched\"';
하면이 방법을 사용하면 예기치 않은 결과가 발생합니다.
이것은 많은 리눅스 배포판에서 사용 가능한 nanorc.sample에서 가져온 것입니다. C 스타일 문자열의 구문 강조 표시에 사용됩니다.
\"(\\.|[^\"])*\"
var s = ' my \\"new\\" string and \"this should be matched\"';
하면이 방법을 사용하면 예기치 않은 결과가 발생합니다.
" \"(\\\\.|[^\\\"])*\" "
ePharaoh가 제공 한대로 대답은
/"([^"\\]*(\\.[^"\\]*)*)"/
위의 내용을 작은 따옴표 또는 큰 따옴표 문자열에 적용하려면 다음을 사용하십시오.
/"([^"\\]*(\\.[^"\\]*)*)"|\'([^\'\\]*(\\.[^\'\\]*)*)\'/
여기에 제공된 대부분의 솔루션은 대체 반복 경로, 즉 (A | B) *를 사용합니다.
일부 패턴 컴파일러가 재귀를 사용하여이를 구현하기 때문에 큰 입력에서 스택 오버플로가 발생할 수 있습니다.
예를 들어 Java : http://bugs.java.com/bugdatabase/view_bug.do?bug_id=6337993
다음과 같은 것 :
"(?:[^"\\]*(?:\\.)?)*"
, 또는 Guy Bedford에서 제공하는 것은 대부분의 스택 오버플로를 방지하는 구문 분석 단계의 양을 줄입니다.
/(["\']).*?(?<!\\)(\\\\)*\1/is
인용 된 문자열과 함께 작동해야합니다.
이것은 PCRE에서 완벽하게 작동하며 StackOverflow와 함께 떨어지지 않습니다.
"(.*?[^\\])??((\\\\)+)?+"
설명:
"
;.*?
{Lazy match}; 비 이스케이프 문자로 끝남 [^\\]
;(.*?[^\\])??
"
)로 끝나지만 짝수 개의 이스케이프 부호 쌍이 앞에 올 수 있습니다 (\\\\)+
. 그리고 그것은 Greedy (!) 선택 사항입니다 : ((\\\\)+)?+
{Greedy matching}, 왜냐면 문자열은 비어 있거나 끝 쌍이 없을 수 있습니다!"(.*?[^\\])?(\\\\)*"
여기에 "및 '모두에서 작동하는 하나가 있으며 처음에 다른 항목을 쉽게 추가 할 수 있습니다.
( "| ') (? : \\\ 1 | [^ \ 1]) *? \ 1
역 참조 (\ 1)를 사용하여 첫 번째 그룹 ( "또는 ')에 정확히 일치합니다.
[^\1]
대체해야하며 .
어쨌든 중요하지 않습니다. 첫 번째 조건은 나쁜 일이 발생하기 전에 항상 일치합니다.
[^\1]
와 함께하는 것이 .
효율적이 정규식을 바꿀 것 ("|').*?\1
하고는 일치합니다 "foo\"
에서 "foo \" bar"
. 즉, [^\1]
실제로 일하는 것은 어렵습니다. @ mathiashansen - 당신은 더 나은 오프 다루기 힘든 고가에있어 (?!\1).
(그래서 전체 정규식, 일부 효율성 정리와, 것 (["'])(?:\\.|(?!\1).)*+\1
(가). +
당신의 엔진을 지원하지 않는 경우 선택 사항입니다.
이전에 다루지 않은 옵션은 다음과 같습니다.
이것은 이스케이프 된 오픈 태그를 정확하게 일치시킬 수 있다는 추가 보너스를 가지고 있습니다.
다음 문자열이 있다고 가정 해 보겠습니다. String \"this "should" NOT match\" and "this \"should\" match"
여기에서 \"this "should" NOT match\"
일치해서는 안되며 일치 "should"
해야합니다. 그 위에 this \"should\" match
일치해야하며 일치 \"should\"
해서는 안됩니다.
먼저 예입니다.
// The input string.
const myString = 'String \\"this "should" NOT match\\" and "this \\"should\\" match"';
// The RegExp.
const regExp = new RegExp(
// Match close
'([\'"])(?!(?:[\\\\]{2})*[\\\\](?![\\\\]))' +
'((?:' +
// Match escaped close quote
'(?:\\1(?=(?:[\\\\]{2})*[\\\\](?![\\\\])))|' +
// Match everything thats not the close quote
'(?:(?!\\1).)' +
'){0,})' +
// Match open
'(\\1)(?!(?:[\\\\]{2})*[\\\\](?![\\\\]))',
'g'
);
// Reverse the matched strings.
matches = myString
// Reverse the string.
.split('').reverse().join('')
// '"hctam "\dluohs"\ siht" dna "\hctam TON "dluohs" siht"\ gnirtS'
// Match the quoted
.match(regExp)
// ['"hctam "\dluohs"\ siht"', '"dluohs"']
// Reverse the matches
.map(x => x.split('').reverse().join(''))
// ['"this \"should\" match"', '"should"']
// Re order the matches
.reverse();
// ['"should"', '"this \"should\" match"']
이제 RegExp를 설명하겠습니다. 이것은 정규식을 세 부분으로 쉽게 나눌 수 있습니다. 다음과 같이 :
# Part 1
(['"]) # Match a closing quotation mark " or '
(?! # As long as it's not followed by
(?:[\\]{2})* # A pair of escape characters
[\\] # and a single escape
(?![\\]) # As long as that's not followed by an escape
)
# Part 2
((?: # Match inside the quotes
(?: # Match option 1:
\1 # Match the closing quote
(?= # As long as it's followed by
(?:\\\\)* # A pair of escape characters
\\ #
(?![\\]) # As long as that's not followed by an escape
) # and a single escape
)| # OR
(?: # Match option 2:
(?!\1). # Any character that isn't the closing quote
)
)*) # Match the group 0 or more times
# Part 3
(\1) # Match an open quotation mark that is the same as the closing one
(?! # As long as it's not followed by
(?:[\\]{2})* # A pair of escape characters
[\\] # and a single escape
(?![\\]) # As long as that's not followed by an escape
)
이것은 아마도 이미지 형식에서 훨씬 더 명확 할 것입니다 : Jex의 Regulex를 사용하여 생성됨
github의 이미지 (JavaScript Regular Expression Visualizer.) 죄송합니다 . 이미지를 포함 할만큼 명성이 높지 않으므로 지금은 링크 일뿐입니다.
다음은 좀 더 발전된이 개념을 사용하는 예제 함수의 요점입니다. https://gist.github.com/scagood/bd99371c072d49a4fee29d193252f5fc#file-matchquotes-js
정규 표현식이 모든 문자열에 대한 은색 총알이 아님을 기억해야합니다. 어떤 것들은 커서와 선형, 수동, 탐색으로 더 간단합니다. CFL은 매우 하찮게 트릭을 할 것이다, 그러나 많은 CFL 구현 (AFAIK)이 없습니다.
https://stackoverflow.com/a/10786066/1794894 의 더 광범위한 버전
/"([^"\\]{50,}(\\.[^"\\]*)*)"|\'[^\'\\]{50,}(\\.[^\'\\]*)*\'|“[^”\\]{50,}(\\.[^“\\]*)*”/
이 버전에는
“
및 닫기 ”
)정규 표현식에 엉망이 되어이 정규 표현식으로 끝났습니다. (작동 방식을 묻지 마십시오.
"(([^"\\]?(\\\\)?)|(\\")+)+"
처음부터 검색하면 작동 할 수 있습니까?
\"((\\\")|[^\\])*\"
일부 파일의 구문 분석을 방해 할 수있는 인용 된 문자열을 제거하려고하는 비슷한 문제에 직면했습니다.
나는 당신이 생각해 낼 수있는 복잡한 정규식을 능가하는 2 단계 솔루션으로 끝났습니다.
line = line.replace("\\\"","\'"); // Replace escaped quotes with something easier to handle
line = line.replaceAll("\"([^\"]*)\"","\"x\""); // Simple is beautiful
읽기 쉽고 아마도 더 효율적일 것입니다.