2010-07-08 4 views
1

정규식을 배우고 있습니다. SQL Select 문에서 열 별칭을 제거하는 메서드가있는 연습을 제안했습니다. 이것은 다음과 같이 작동합니다 :C#과 정규 표현식을 사용하여 SQL select 문에서 별칭 제거하기

  • 방법은 AS 키워드와 SQL SELECT 문에서 별칭을 제거 할 수 있습니다 이없이 SQL SELECT 문에서 별칭을 제거 할 수 있습니다
  • 방법 "A AS COLUMNA을 선택" 는 AS 키워드 :합니다 ( 연결 작업 문자 등) "작업 문자"가 포함 된 SQL SELECT 문에서 별칭을 제거 할 수 있습니다
  • 방법을 "COLUMNB B를 선택" "를 선택 '안녕하세요 || 'world!'AS HelloWorld "

지금까지 특별한 경우에만 작동하는 두 가지 방법을 만들었습니다. 다음 코드는 제가 한 일과 제가 직면 한 문제에 대한 요약을 제공합니다.

static void Main(string[] args) 
{ 
    string cols1 = "ColA as AliasA, ColB AliasB , As As ASasas, Asasasas as As"; 
    string cols2 = "'aaa' || 'bbb' AS AliasC , 'ccc' || 'ddd' AliasD"; 

    string answer1 = RemAliases(cols1);  // Works fine 
    string answer2 = RemAliases2(cols2); // Works fine 
    string answer3 = RemAliases2(cols1); // Doesn't work 
    string answer4 = RemAliases(cols2);  // Doesn't work    
} 

static string RemAliases2(string inputSql) 
{ 
    string pattern1 = @"(.+)\s+AS\s+\w+"; 
    string replacement1 = "$1"; 
    string pattern2 = @"(.+)\s+\w+"; 
    string replacement2 = "$1"; 
    string result = Regex.Replace(inputSql, pattern1, replacement1, RegexOptions.IgnoreCase); 
    result = Regex.Replace(result, pattern2, replacement2, RegexOptions.IgnoreCase); 
    return result; 
} 

static string RemAliases(string inputSql) 
{ 
    string pattern1 = @"(\w+)\s+AS\s+\w+"; 
    string replacement1 = "$1"; 
    string pattern2 = @"(\w+)\s+\w+"; 
    string replacement2 = "$1"; 
    string result = Regex.Replace(inputSql, pattern1, replacement1, RegexOptions.IgnoreCase); 
    result = Regex.Replace(result, pattern2, replacement2, RegexOptions.IgnoreCase); 
    return result; 
} 

내가 기대 없습니다 "RemAliases()"를 "cols2"와 잘 작동하기 때문에 "\ w +"는 일치하지 않습니다 "|"문자. 하지만, "RemAliases2()"도 "cols1"과 잘 작동 할 것으로 기대하고있었습니다. 누군가가 왜 "RemAliases2()"가 "cols1"의 경우 제대로 작동하지 않는지 알기 위해 도움을 주실 수 있습니까? 이 정규 표현식을 사용한 방식에 대해 다른 종류의 제안을 제공하십시오.

미리 감사드립니다.

PS : 나는 (.+)\s+AS\s+\w+와 .NET 2.0

답변

0

문제 중 하나를 사용하고하면 (.+) 욕심 때문이다. 즉, 문자가 더 이상 일치하지 않아 새로운 줄을 의미 할 때까지 계속 진행됩니다. 네가 넣어 준다면? + 뒤에는 게으 르기 때문에 공간이 \ s와 일치하기 때문에 첫 번째 공간을 찾으면 중지됩니다.

다음 문제는. 공백도 일치합니다. 따라서 ColB AliasB , 사례가있는 경우 정규 표현식의 다음 부분과 일치하는 "AS"가 나타날 때까지 계속 진행됩니다. 이 경우, 다음 그룹의 일부로 발견됩니다. 따라서 RemAliases 함수에서 사용한 것처럼 \ w +를 사용하는 것이 좋습니다.

지금까지 내가 간 것까지입니다. 나중에 다른 것을 찾으면 나중에 편집 할 것입니다. 그 동안, 당신이 배우고 있기 때문에, 다음은 정규 표현식을 쓸 필요가있을 때 보통 사용하는 꽤 좋은 참고 자료입니다. Regex Reference

0

RemAliases2가 cols1에서 작동하지 않는 이유는. + 욕심입니다 - 가능한 한 많이 취합니다.

(.+)이 전체 라인을 차지할 것입니다. 그리고 정규 표현식 엔진은 정규 표현식의 나머지 부분을 일치 시키려고 뒤로 물러 설 것입니다. 그래서 경기가 될 것이다 : 나는 다른 줄에 정규 표현식의 각 부분을 세분화하고, 이후 ""의 내부 일치 도착하여 문자열의 일부를 표시했습니다

(.+) --> "ColA as AliasA, ColB AliasB , As As ASasas, Asasasas" 
\s+ --> " " 
AS --> "as" 
\s+ --> " " 
\w+ --> "As" 

-> .

각 정규식을 차례로 적용하지만 전체 문자열에 적용됩니다. 테스트 문자열의 텍스트 순서 때문에 제대로 작동하는 것처럼 보일뿐입니다. 전혀 규모가 없다. (경우와 용)

한 가지 더 좋은 시작이 될 것이다 : (? +)

(.+?)(\s+as\s+\w+\s*)(,|$) 

내가 아닌 욕심하기 위해 + 변경했습니다, 나는 후 공백의 옵션을 추가했습니다 앨리어스 열 이름이지만 쉼표 (\ s *) 앞에 있고 쉼표를 끝에 추가하여 식 (, | $)을 올바르게 끝내고 선택 영역의 각 필드에 대해 여러 번 반복 할 수 있습니다 절.

그러나 이것은 하나의 일치 하나만 ​​않습니다 (정규식은 알고 있지만 C#은 아닙니다. 따라서 C#에서는 작동하는 방식을 정확히 말할 수 없지만 개념은 꽤 일반적입니다). 문자열을 여러 번 반복하거나 전역 플래그로 함수를 호출해야합니다. (Java에서는 replace() 대신 replaceAll()을 호출하면됩니다. C#이 비슷한 구문을 가지고 있다고 가정합니다.)

전역 적으로 적용되고 대체 문자열에 $ 1과 $ 3을 모두 삽입하면 의 수정 cols1을 제공 :

COLA, COLB ALIASB로서, Asasasas

그런 다음, 당신이 열심히 인 AS, O/w는 경우가있다!

0

정규 표현식이 안정적으로 작동하려면 .+으로 바로 가기를 시도하지 말고 일치해야하는 부분을 철저히 조사해야합니다. 아래의 설명은 다소 오랜 시간 지속됩니다. 정규 표현식을 만들 때 내가 생각한 과정입니다.

예제에 따라 colA과 같은 식별자 또는 'aaa' || 'bbb'과 같이 작은 따옴표로 묶은 문자열을 연결 한 식별자가 있습니다. 식별자는 \w+, 일치 문자열은 '[^']*'(?:\s*\|\|\s*'[^']*')*과 일치시킬 수 있습니다. 문자열에 대한 나의 정규 표현식 (regex)을 사용하면 임의의 수의 문자열을 연결할 수 있습니다. 연결하지 않아도됩니다 (예 : 단일 인용 문자열).

이 두 가지 중 하나와 일치하도록 \b\w+\s+|'[^']*'(?:\s*\|\|\s*'[^']*')*\s*을 사용할 수 있습니다. 식별자 다음에 \s+을 추가했습니다. 그 이유는 다음과 같은 공백으로 구분해야하기 때문입니다. 연결 문자열의 경우 \s*은 분리 문자 공간을 선택적으로 만듭니다.

식별자 또는 문자열 뒤에 선택적으로 키워드 As이 올 수 있습니다. 키워드가있는 경우 뒤에 공백이 와야합니다. 이것을 (As\s+)?으로 코딩 할 수 있습니다.

마지막으로이 다음에 다른 식별자가옵니다. 이 문자는 \w+과 쉽게 일치합니다.

모두 함께 퍼팅, 우리는이 정규식을 얻을 :

(\b\w+\s+|'[^']*'(?:\s*\|\|\s*'[^']*')*\s*)(As\s+)?\w+ 

나는 첫 번째 부분 주위에 캡처 그룹을 넣어. 우리는 검색과 교체를 위해 그것을 필요로 할 것입니다. 이 정규식 일치를 단순히 열 이름이나 문자열 연결로 바꾸면 "있는 그대로"부분이 효과적으로 제거됩니다. 대체 텍스트는 간단히 $1입니다.

또는 C#에서

:

result = Regex.Replace(inputSql, 
    @"(\b\w+\s+|'[^']*'(?:\s*\|\|\s*'[^']*')*\s*)(As\s+)?\w+", "$1", 
    RegexOptions.IgnoreCase); 
관련 문제