2010-02-03 4 views
4

Javascript에서 정규 표현식을 사용하여 주어진 입력 문자열을 주어진 출력 문자열로 변환하는 데 문제가 있습니다. 내가 성취하고자하는 것이 정규 표현식으로 수행 될 수 있는지, 아니면 다른 어떤 수단을 사용하여 가장 효율적 일지는 확실치 않습니다. 나는 누군가가 도움을 줄 수 바라고 있어요 :자바 스크립트 문자열 대체 -이 작업을 수행하는 가장 좋은 방법은 무엇입니까?

나는 다음과 같은 입력 문자열이 있습니다

그것이 #> 사이에서 발견 될 때마다 내가 탈출 버전 \' 각 인용 ' 문자를 교체해야
#> Some text goes here, and a 'quoted string' is inside. 
<# something with 'quotes' #> 
Another 'quoted string' is found <# 

<# 서열.

원하는 출력 문자열 다음 <# something with 'quotes' #> 부분에 따옴표 탈출되지 않았 음을

#> Some text goes here, and a \'quoted string\' is inside. 
<# something with 'quotes' #> 
Another \'quoted string\' is found <# 

참고 만 따옴표 #><# 사이에서 발견.

나는이을 수행 할 다음 코드를 사용하고 있지만이 같은 일 (참고 할 수있는 더 좋은 이상의 효율적인 방법 찾으려면 : 캐리지 리턴 및 탭이에서 찾을 수 없습니다로 보장을 내 입력 문자열, 그래서 아래의 방식)에서 사용하는 것이 안전 해요 :

var s = ... some input string ...; 

// Replace all "<#" sequences with tabs "\t" 
s = s.split("<#").join("\t"); 

var i = 1; 
do 
{ 
    // Replace a single quote that is found within 
    // #> and <# block with a carriage return. 
    s = s.replace(/((^|#>)[^\t]*?)'/g, "$1\r"); 

    // Continue replacing single quotes while we're 
    // still finding matches. 
    s = s.split("\r"); 
    if (s.length < ++i) 
     break; 
    s = s.join("\r"); 
} 
while (true); 

// Replace each instance of a carriage return 
// with an escaped single quote. 
s = s.join("\\'"); 

난 그냥 하나의 정규 표현식을 사용하지 않는 주된 이유는 내가 그것을 대체 할 수없는 것 수 있다는 것입니다 1 개 이상의 작은 따옴표 문자. 그래서 do/while 루프를 사용하여 모두가 이스케이프 처리되는지 확인했습니다.

누군가 더 좋은 방법이 있습니까 (제발).

답변

4

이 정규식은 따옴표 일치하지 내부 <# ... #>

'(?=((?!#>)[\s\S])*(<#|$)) 

간단한 설명 : 일반 영어

'    # match a single quote 
(?=   # start positive look ahead 
    (   # start capture group 1 
    (?!  #  start negative look ahead 
     #  #  match the character '#' 
     >  #  match the character '>' 
    )   #  end negative look ahead 
    [\s\S] #  match any character from the set {'0x00'..'ÿ'} 
)*   # end capture group 1 and repeat it zero or more times 
    (   # start capture group 2 
    <   #  match the character '<' 
    #   #  match the character '#' 
    |   #  OR 
    $   #  match the end of the input 
)   # end capture group 2 
)    # end positive look ahead 

또는 :

일치 작은 따옴표만을 찾고 앞으로 '< #'(또는 입력의 끝) 부분 문자열을 볼 수 있습니다. 단일 인용 부호와 '< #'(또는 입력의 끝) 사이에 '#>'이 발생합니다.

그러나이 정규식 솔루션 당신이 지금 가지고있는 것보다 더 효율적되지 않습니다 (같이 효율적인 빠르게 실행).

왜 현재 접근 방식이 아닌 다른 것을 찾고 있습니까? 당신의 솔루션은 나에게 잘 어울립니다.

+0

'\ r '문자에 split() 및 join()을 사용하지 않습니다. 상당히 많은 입력 문자열 (10,000 자 정도)에서 성능이 어떻게되는지 잘 모르겠습니다. 심층적 인 설명을 주셔서 감사합니다. 나 같은 사람들에게 매우 유용합니다. 지금 당장 정규식으로 도핑하는 사람 : – Doug

+1

문제 없습니다. Doug. 간략한 설명은 여전히 ​​조금 은폐 될 수 있습니다 (단 설명이 생성 된 것입니다 ...). 당신이 필요로하는 경우에, 나는 평범한 영어로 (잘하면) 이해할 수있는 설명을 게시했다. 너가 그것을 필요로하지 않으면, 잘, 아마 다른 누군가는 그것으로부터 혜택을받을지도 모른다! :) –

+0

많이 감사드립니다 :) 왼쪽 측면 (암시적임) 또는 오른쪽면 (암시 적)의 <없음 #>이없는 경우에만 발견 된 유일한 문제입니다. 예를 들어, "$ ('# <= = (' ') #>') func();" #)/g, "\\ '"); 최종 견적을 놓친다. 그러나 당신의 정규 표현식에 대해 대단히 감사합니다. 매우 통찰력이 있으며 긍정적/부정적 예측을 많이하지는 않았습니다. – Doug

0

다음 정규 표현식은 수천 개의 문자에 대해 방화 광 콘솔에서 매우 빠르게 작동합니다.

str.replace(/'|\\'/g, "\\'") 
    .replace(/(<#[^#\>]*)\\'([^\\']+)\\'([^#\>]*#\>)/g, "$1'$2'$3") 

첫 번째는 모든 따옴표를 대체하고 이미 '모든 < # ... \에 대한 두 번째 모습을'\로 따옴표를 탈출 ... \ '...#> 대체하고 < # ... '...' '...로 대체합니다. #>

관련 문제