2008-08-29 3 views
8

최근에 X/Motif에서 Qt로 옮긴 C++ 코드 기반으로 작업하고 있습니다. 내가 부울 (X에서) 부울로 모든 발생을 바꿀 펄 스크립트를 작성하려고합니다. 이 스크립트는 단순한 대체 작업을 수행합니다.부울을 부울로 바꿀 Regex

s/\bBoolean\b/bool/g 

몇 가지 조건이 있습니다.

1) 코드에 CORBA가 있고 \ b가 이 아닌이 변경되어야하는 CORBA :: Boolean과 일치합니다.
2)가 (문자열로, 즉 "부울을"발견 된 경우가

업데이트) 일치하지해야합니다

는 # 1의 경우, 내가 # 2의 lookbehind

s/(?<!:)\bBoolean\b/bool/g; 

사용 , 나는 선견지명을 사용했다.

s/(?<!:)\bBoolean\b(?!")/bool/g</pre> 

이것은 내 상황에서 가장 잘 작동하지만 다음 개선 사항은 어떻게됩니까?

3) 문자열 중간에 일치하지 마십시오 (감사 코드 nohat).
4) 의견에 일치하지 마십시오. (// 또는/** /)

+0

사이드 노트 : http://stackoverflow.com/questions/72312/how-should-i-capitalize-perl#72757 – szabgab

답변

0

조건 1 개 시도를 해결하려면 :

s/[^:]\bBoolean\b(?!")/bool/g 

에서 [^] 이외의 문자와 일치 말한다 "".

1
s/[^:]\bBoolean\b[^"]/bool/g 

편집 : 벳, 다시 맞습니다. 나를 때리는 +1.

3

S/[^] \ bBoolean \의 B/BOOL/g

부울에서 인 경우에 문자열과 일치하지 않음 [becuase 줄의 시작^("?!) ]는 "일치하지 않는 문자와 일치합니다 :".

2

부울이 문자열의 마지막 부분이지만 그 중간 부분이 아닌 경우에만 일치합니다. 문자열에 있지 않은지 확인하려면 문자열 앞에 오는 짝수 개의 인용 부호를 일치시켜야합니다 (여러 줄 문자열이 없다고 가정). s 및 이스케이프 된 내장 된 따옴표 없음).

0

3) 문자열 중간에 있으면 일치하지 마십시오 (감사합니다).

". * Boolean. *"을 확인하기 위해 reg ex를 작성할 수 있습니다. 하지만 문자열 안에 따옴표 (")가 있으면 어떻게 될까요? 따라서 패턴을 제외하지 않을 (\") 수있는 작업이 더 많습니다.

4) 의견에 일치하지 마십시오. (// 또는/* * /)

'//'의 경우 //를 제외 할 정규 표현식을 사용할 수 있습니다.* 그러나 처음에는 정규식을 사용하여 // 주석 ((. *) (//.*))에 대한 전체 줄을 비교 한 다음 $ 1 (첫 번째 일치 패턴)에서만 교체를 적용하는 것이 좋습니다.

/* * /의 경우 여러 줄 패턴이므로 더 복잡합니다. 하나의 접근법은 먼저 여러 줄의 주석을 일치시키기 위해 전체 코드를 실행 한 후 ... (. *) (/*.**/) (. *)와 같은 부분과 일치하지 않는 부분만을 추출하는 것입니다. 하지만, 실제 정규식은 더 복잡 할 것입니다. 단 한 줄이 아니고 여러 줄로 된 주석이 더 많을 것입니다.

이제/* 또는 */inside // 블록을 사용하면 어떻습니까? (나는 왜 당신이 그것을 가지고 있을지 모른다. 그러나 Murphy의 법칙은 당신이 그것을 가질 수 있다고 말한다). 분명히 몇 가지 방법이 있지만 내 생각은 정규식이 얼마나 나쁘게 보이는지 강조하는 것입니다.

여기 내 제안은 C++ 용 어휘 도구를 사용하고 부울 토큰을 bool로 바꾸는 것입니다. 당신의 생각?

0

perl에서 전체 C 파서를 작성하지 않으려면 균형을 맞추려고합니다. 변경해야 할 필요성에 따라 매우 제한적인 s ///와 같은 일을하는 경향이 있습니다. 그리고 나서/Boolean /과 일치하는 것은 인간의 의사 결정을위한 예외 파일에 기록됩니다. 그런 식으로 C 중간 문자열, 여러 줄 주석, 조건부 컴파일 된 텍스트 등을 파싱하지 않으려 고합니다.

0
  1. ...
  2. ...
  3. 은 문자열의 중간에있는 경우 (nohat 덕분에) 일치하지 않습니다.
  4. 댓글에있는 내용과 일치하지 마십시오. (// 또는/** /)

없음이 간단한 정규식으로 할 수 있습니다. 이를 위해서는 을 매번 문자를 왼쪽에서 오른쪽으로 쳐보고 다른 것들의 문자열에있는 여러 줄 주석의 주석을 구분할 수있을 정도로 어떤 종류인지 결정해야합니다. "다른 내용"부분에 변경하려는 내용이 포함되어 있는지 확인해야합니다.

이제 정확한 C++의 주석 및 문자열에 대한 구문 규칙을 알 수 없으므로 다음 내용은 부정확하고 완전히 undebugged 될 것이지만 복잡해 짐을 알 수 있습니다 반대.

my $line_comment  = qr! (?> // .* \n?) !x; 
my $multiline_comment = qr! (?> /\* [^*]* (?: \* (?: [^/*] [^*]*)?)*)* \*/) !x; 
my $string   = qr! (?> " [^"\\]* (?: \\ . [^"\\]*)* ") !x; 
my $boolean_type  = qr! (?<!:) \b Boolean \b !x; 

$code =~ s{ \G (
     $line_comment 
    | $multiline_comment 
    | $string 
    | ($boolean_type) 
    | . 
) }{ 
    defined $2 ? 'bool' : $1 
}gex; 

모든 것을 복잡하게 설명해달라고 요청하지 마십시오. 하루가 걸릴 것입니다. 그냥 제프   Friedl의 Mastering Regular Expressions 구입하고 읽고 무슨 일이 일어나고 있는지 정확히 이해하고 싶다면.

0

는 "문자열의 중간에 '부울'"부분은

m/"[^"]*Boolean[^"]*"/ 

그리고이 경우 같은과 코드에서의 발생이 있다면 내가 먼저 확인할 것, 조금 가능성 소리 아무 것도 없거나 몇 가지 경우에만 무시합니다.

1
#define Boolean bool 

전처리 기가 이것을 처리하게하십시오. 불리언 값이 나타날 때마다 수동으로 수정하거나 정규 표현식이 실수가 아니길 바랄 수 있습니다. 얼마나 많은 매크로를 사용 하느냐에 따라 cpp 밖으로 덤프 할 수 있습니다.