2012-09-11 2 views
6

문자열에 하위 문자열이 있지만 특정 위치에만 있는지 확인할 수 있습니까?문자열에 단어가 있지만 특정 위치에만 있는지 확인하십시오.

예 문자열 : 당신의 좋아하는 색상은 무엇

입니까? 내가 문자열이 나는 보통 이렇게 특정 단어가 포함되어 있는지 확인하고 싶었다면 내 [좋아하는] 색상은

파란색입니다 : 내가 필요한 것은

var 
    S: string; 
begin 
    S := 'What is your favorite color? my [favorite] color is blue'; 
    if (Pos('favorite', S) > 0) then 
    begin 
    // 
    end; 
end; 

가 결정하는 경우 단어 좋아이 문자열에 존재하지만, 위의 코드 샘플에서 분명히하지 않는 [] 기호 안에 나타나면 무시됩니다. 우리는 부울 함수에 코드를 넣어 경우

그래서, 일부 샘플 결과는 다음과 같습니다

TRUE : 당신의 좋아하는 색상은 무엇입니까? 내 [내가 좋아하는] 색상은 파란색입니다

TRUE : 당신의 좋아하는 색상은 무엇입니까? 내 [ㅋ ㅋ ㅋ ㅋ] 색상은 파란색입니다

FALSE : 당신의 ㅋ ㅋ ㅋ ㅋ 색상은 무엇입니까? 단어 좋아하는이 그들 내부에 있는지 여부에 관계없이 [] 기호 외부에서 검출되기 때문에 내 [일부 좋아하는] 색상은 블루

처음 두 샘플 위에 해당한다.

좋아하는 단어가 있더라도 [] 기호 안에 만 나오므로 기호의 바깥에만 있는지 확인해야하기 때문에 세 번째 예제는 false입니다.

그래서 단어 (이 예에서는 즐겨 찾기)가 문자열에 나타나는지를 결정해야하지만 단어가 [] 기호로 둘러싸여 있다면 사실을 무시해야합니다.

+0

아이디어 : 1) '\ s'에 문자열을 분할하고 네 번째 요소를 확인하십시오. 2)'마음에 드는'이 있는지 확인하십시오 (단어 주위의 공백에주의하십시오). 3) 문자열을 물음표 '?'로 나눈 다음 '즐겨 찾기'가 있는지 확인하십시오. –

+5

검색 '[', 검색이 발견되면 ']', 중간에 '[]'포함하여 삭제하고 즐겨 찾기를 검색하십시오. –

+0

또는 정규 표현식 (XE에 포함 된 단위 포함)을' '\ b'+ wordtofind + '\ b'' 정규식으로 사용하십시오. 당신이주의해야 할 유일한 것은 '그것은 좋아하는가요?'입니다,'? '는 일치하지 않을 것입니다. –

답변

8

나는 대괄호로 묶인 문자열을 삭제하고 그 후에 문자열을 검색하는 것에 대해 Sertac's idea을 좋아합니다. 여기

function ContainsWord(const AText, AWord: string; AWholeWord: Boolean = True; 
    ACaseSensitive: Boolean = False): Boolean; 
var 
    S: string; 
    BracketEnd: Integer; 
    BracketStart: Integer; 
    SearchOptions: TStringSearchOptions; 
begin 
    S := AText; 
    BracketEnd := Pos(']', S); 
    BracketStart := Pos('[', S); 
    while (BracketStart > 0) and (BracketEnd > 0) do 
    begin 
    Delete(S, BracketStart, BracketEnd - BracketStart + 1); 
    BracketEnd := Pos(']', S); 
    BracketStart := Pos('[', S); 
    end; 
    SearchOptions := [soDown]; 
    if AWholeWord then 
    Include(SearchOptions, soWholeWord); 
    if ACaseSensitive then 
    Include(SearchOptions, soMatchCase); 
    Result := Assigned(SearchBuf(PChar(S), StrLen(PChar(S)), 0, 0, AWord, 
    SearchOptions)); 
end; 

문자열 조작없이 포인터 CHAR 반복을 사용하는 함수의 최적화 된 버전은 : 여기에서 전체 단어 및 대소 문자를 검색 확장 코드 샘플이다. 이전 버전과 비교하여이 예에서는 닫는 대괄호가없는 문자열 (예 : My [favorite color is)을 처리합니다. 이러한 문자열은 괄호가 없어서 True로 평가됩니다.

원칙은 char에 의해 전체 문자열 char을 살펴보고 여는 괄호를 찾으면 그 괄호에 닫는 쌍이 있는지 살펴 보는 것입니다. 그렇다면 여는 괄호가 검색된 단어를 포함 할 때까지 저장된 위치에서 하위 문자열이 있는지 확인하십시오. 그렇다면 기능을 종료하십시오. 그렇지 않은 경우 저장된 위치를 닫는 대괄호로 이동하십시오. 여는 대괄호에 고유 한 닫는 쌍이 없으면 저장된 위치에서 전체 문자열의 끝까지 단어를 검색하고 함수를 종료하십시오. 이 코드 follow this link의 주석 버전에 대한

.

function ContainsWord(const AText, AWord: string; AWholeWord: Boolean = True; 
    ACaseSensitive: Boolean = False): Boolean; 
var 
    CurrChr: PChar; 
    TokenChr: PChar; 
    TokenLen: Integer; 
    SubstrChr: PChar; 
    SubstrLen: Integer; 
    SearchOptions: TStringSearchOptions; 
begin 
    Result := False; 
    if (Length(AText) = 0) or (Length(AWord) = 0) then 
    Exit; 
    SearchOptions := [soDown]; 
    if AWholeWord then 
    Include(SearchOptions, soWholeWord); 
    if ACaseSensitive then 
    Include(SearchOptions, soMatchCase); 
    CurrChr := PChar(AText); 
    SubstrChr := CurrChr; 
    SubstrLen := 0; 
    while CurrChr^ <> #0 do 
    begin 
    if CurrChr^ = '[' then 
    begin 
     TokenChr := CurrChr; 
     TokenLen := 0; 
     while (TokenChr^ <> #0) and (TokenChr^ <> ']') do 
     begin 
     Inc(TokenChr); 
     Inc(TokenLen); 
     end; 
     if TokenChr^ = #0 then 
     SubstrLen := SubstrLen + TokenLen; 
     Result := Assigned(SearchBuf(SubstrChr, SubstrLen, 0, 0, AWord, 
     SearchOptions)); 
     if Result or (TokenChr^ = #0) then 
     Exit; 
     CurrChr := TokenChr; 
     SubstrChr := CurrChr; 
     SubstrLen := 0; 
    end 
    else 
    begin 
     Inc(CurrChr); 
     Inc(SubstrLen); 
    end; 
    end; 
    Result := Assigned(SearchBuf(SubstrChr, SubstrLen, 0, 0, AWord, 
    SearchOptions)); 
end; 
+1

위대한 답은 특히 유용하다. 의견을 가진 답에 대한 링크는 소화하기가 쉽고 이해가 쉽다. –

+1

감사! 어쨌든, 정규식은 당신이 필요로하는 것을 (그리고 확실하게 더 쉽게) 할 수있는 올바른 방법이다.하지만 다른 한편으로는, 이것은이 특정 작업에 더 직설적이다. (정규 표현식은 적어도 구문 분석 할 필요가 있기 때문에 더 효율적이다. 표현이 일치하기 시작하기 전에). 예를 들어 구문 분석기를 만들지 않으면이 일치와 같은 많은 유사한 작업을 어디에서 수행 할 것인가?이 솔루션은 정규식을 포함하는 것보다 가벼울 수 있습니다. 그러나 주된 이유는 왜 내가이 글을 올렸는가하는 이유 중 하나는 순수한 델파이를 사용한 답이 없다는 것입니다. – TLama

7

regular expressions에는 look-around이라는 것이 있습니다. 귀하의 경우에는 부정적인 lookbehind로 그것을 해결할 수 있습니다 : 그것은 앞에 bracket이 선행되지 않는 한 "favorite"를 원합니다. 그것은 다음과 같이 수 : 단계별로

(?<!\[[^\[\]]*)favorite 

단계 : 종료 부정적인 [^\[\]]* : (?<! 선택적 없음 또는 폐쇄 또는 괄호를 열고되지 않은 더 많은 것들이 다음에, 우리는 \[ 찾고있는 부정적인 lookbehind의 접두어 lookbehind는 )이고 그 다음은 favorite입니다.

+0

나는 너의 우아하고 적절한 해결책이라고 생각한다. – diegoaguilar

0

"문제를"대괄호로 묶지 않은 제공된 문자열을 찾아보십시오 "라고 다시 생각할 수 있습니다. 문제가 해당되는 경우 [^\[]favorite[^\]]과 같은 간단한 정규식을 사용할 수 있습니다.

관련 문제