정규식(정규 표현식, Regular Expression) > vb.net

본문 바로가기

vb.net

[기타] 정규식(정규 표현식, Regular Expression)

회원사진
하나를하더라도최선을
2024-04-17 14:40 115 0

본문



6f0a85100beff04e7bc0dcecb3f291e7_1713332068_0755.jpg


 정규식(정규 표현식, Regular Expression)은 텍스트에서 특정 패턴을 찾기 위해 사용하는 문자열입니다. 컴퓨터 과학에서 널리 사용되는 이 툴은 복잡한 검색과 문자열 치환 작업을 간편하게 수행할 수 있게 해줍니다. 여러 프로그래밍 언어 및 텍스트 편집 도구에서 지원합니다.

정규식의 기본 구성 요소

  1. 리터럴(Literals): 텍스트 그대로의 문자입니다. 예를 들어, 정규식 abc는 "abc"라는 문자열과 일치합니다.

  2. 메타 문자(Meta Characters): 특별한 의미를 가진 문자로, 패턴을 구성하는 데 사용됩니다. 자주 사용되는 메타 문자에는 다음이 포함됩니다.

    • .: 어떤 한 문자와 일치 (개행 문자 제외)
    • ^: 입력의 시작과 일치
    • $: 입력의 끝과 일치
    • *: 앞의 요소가 0회 이상 반복
    • +: 앞의 요소가 1회 이상 반복
    • ?: 앞의 요소가 0회 또는 1회 등장
    • |: or 조건을 표현 (A|B는 A 또는 B)
    • \: 다음 문자를 리터럴로 취급 (메타 문자가 아닌 문자로)
  3. 문자 클래스(Character Classes): 특정 집합 중 하나의 문자와 일치시킵니다.

    • [abc]: 'a', 'b', 또는 'c'와 일치
    • [^abc]: 'a', 'b', 'c'를 제외한 모든 문자와 일치
    • [a-z]: 모든 소문자와 일치
    • [A-Z]: 모든 대문자와 일치
    • [0-9]: 모든 숫자와 일치
    • \d: 모든 숫자와 일치 (digit)
    • \D: 숫자가 아닌 모든 문자와 일치
    • \w: 알파벳 문자, 숫자, 언더스코어(_)와 일치
    • \W: \w가 아닌 문자와 일치
    • \s: 모든 공백 문자 (스페이스, 탭, 줄바꿈 등)와 일치
    • \S: 공백이 아닌 모든 문자와 일치
  4. 수량자(Quantifiers): 앞선 문자 또는 그룹이 몇 번 반복되는지를 지정합니다.

    • {n}: 정확히 n번 반복
    • {n,}: 최소 n번 반복
    • {n,m}: 최소 n번 최대 m번 반복
  5. 그룹화(Grouping): 소괄호 ()를 사용하여 표현식을 그룹으로 묶습니다. 그룹화를 통해 여러 작업을 수행할 수 있으며, 추출이나 참조가 가능합니다.

정규식의 활용 예시

  • 이메일 주소 검증: ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$
  • 전화번호 형식 확인: \d{2,3}-\d{3,4}-\d{4}
  • URL 확인: https?://(?:www\.)?.+

 

1. 이메일 주소 검증

이메일의 유효성을 확인하기 위해 다음과 같은 정규식을 사용할 수 있습니다.

regexCopy code
^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$

이 정규식은 이메일이 일반적으로 사용되는 문자로 시작하고, "@" 기호, 도메인 이름, 마지막으로 점(".") 뒤에 두 글자 이상의 도메인 확장자가 오는 패턴을 검사합니다.

2. URL 유효성 검사

웹사이트 주소(URL)의 유효성을 검사하기 위해 사용될 수 있는 정규식입니다.

regexCopy code
https?://(?:www\.)?[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,6}\b(?:/[-a-zA-Z0-9@:%_\+.~#?&//=]*)?

이 패턴은 http 또는 https로 시작하고, 선택적으로 www.가 포함되며, 도메인 이름과 확장자를 포함하고, 선택적으로 경로와 쿼리 문자열을 포함할 수 있습니다.

3. 전화번호 형식 확인

다양한 형태의 전화번호를 검사하는 간단한 예시입니다.

regexCopy code
\+?\d{1,3}?[-.\s]?\(?\d{1,3}\)?[-.\s]?\d{1,4}[-.\s]?\d{1,4}

이 정규식은 국제 코드(선택적), 지역 코드(괄호 내에 있을 수 있음), 그리고 번호를 포함하여 다양한 형태의 전화번호와 일치합니다.

4. 비밀번호 복잡성 검사

보안 강화를 위해 특정 조건을 만족하는 비밀번호를 검사하는 정규식입니다.

regexCopy code
^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$

이 정규식은 적어도 하나의 소문자, 대문자, 숫자, 특수 문자를 포함하고 총 8자 이상인 비밀번호와 일치합니다.

5. 코드에서 주석 제거

프로그래밍 코드에서 C 스타일의 주석을 제거할 때 사용할 수 있는 정규식입니다.

regexCopy code
/\*[^*]*\*+(?:[^/*][^*]*\*+)*/

이 정규식은 /*로 시작하고 */로 끝나는 멀티라인 주석을 찾아냅니다.

6. HTML 태그 제거

웹 페이지나 다른 HTML 소스에서 모든 태그를 제거하고 텍스트만 추출하려면 다음과 같은 정규식을 사용할 수 있습니다.

regexCopy code
<[^>]+>

이 정규식은 <로 시작하고 >로 끝나는 모든 문자열과 일치하여, HTML 태그를 찾아내고 제거합니다.

정규식은 이러한 예시 외에도 로그 분석, 데이터 추출, 입력 검증 등 다양한 분야에서 매우 유용하게 활용됩니다. 각 경우에 맞게 적절한 패턴을 설계하여 활용할 수 있습니다.


주의사항

정규식은 매우 강력하지만, 오용하면 의도치 않은 결과를 초래할 수 있습니다. 복잡하고 긴 정규식은 가독성을 저하시키고, 유지보수가 어려울 수 있습니다. 따라서 간결하고 명확한 패턴 설계가 중요합니다.

정규식은 다양한 프로그래밍 언어 및 도구에서 필수적인 요소로 자리 잡고 있습니다. 그 효용성 덕분에 데이터 검증, 처리, 분석 작업에서 빈번히 사용됩니다.




일단 정규식이라 함은 다들 아시겠지만 문자열이 특정한 패턴에 해당하는지 검사하거나 특정 패턴을 가진 부분을

추출하기 위해서 사용합니다.

문자열을 파싱해서 할 수도있지만 비용이 많이 드는 반면에 정규식을 사용하면 정확하고 빠르게 수행을 할 수 있고,

다른 많은 언어에서도 지원을 하니 뭐 많이들 사용하시는 자바스크립트 등에서 효과적으로 사용할 수 있는 장점이 있을 것 같고요...

정규식 문법을 알아야 한다는 단점이 있을 거 같습니다.

일단 정규식은 공식적으로 jdk 1.4 버전 이상에서 사용할 수 있습니다.

그래서... 가장 큰 장점은 자바 api에서 공식 지원하므로 까다로운 메서드나 클래스를 만들지않고 바로 사용할 수 있다는 점을 꼽고 싶습니다.

 

정규식은 자바 예약어와 같은 역할을 하는 특수문자들이 있습니다.

 

정규식을 보면 첨에 보면 좀 당황하게 되는 부분이 괄호였습니다. 괄호의 쓰임새를 보겠습니다.

괄호는 (), {}, [] 일케 3 종류를 씁니다.

()는 괄호 안에 있는 문자나 문자열을 하나의 문자처럼 취급을 합니다.

예를 들어 (aa) 일케 하면 꼭 aa 라는 것이죠~~

{}는 괄호 앞에 있는 문자의 반복횟수를 나타냅니다.

{2}는 문자가 두번 반복된다. {2,}는 문자가 두번 이상 반복된다. {2, 5}는 문자가 2번 이상 5번 이하로 반복된다.

(aa)하고 a{2} 하고는 같은 패턴인 것을 알 수 있습니다.

[]는 하나의 문자를 나타냅니다. char 라고 보셔도 무관할 거 같습니다.

근데 []는 범위를 줄 수도 있습니다. 범위를 주는 방법은 두가지가 있습니다.

첫번째는 [aeho] 이런 방식입니다. 이것은 어떤 한 문자가 'a' or 'e' or 'h' or 'o' 라는 것을 나타냅니다.

두번째는 -를 사용하는 방법입니다. [a-d] 일케하면 'a' or 'b' or 'c' or 'd' 라는 것을 나타냅니다.

이 두가지 방식을 함께 사용할 수도 있는데...[a-zA-Z] 일케하면 다들 아시겠지만...

영문자를 나타냅니다.

 

그렇다면 괄호를 함께 사용해서 (kor[1-3]{2,}ea){2} 이런 정규식은 kor22eakor312ea 와 같은 문자열을 나타낼 수 있겟죠...

 

[]괄호의 안에있는 범위중 특정한 것들을 골라서 미리 정해놓은 것이 있습니다. 이것이 '정규식 클래스'입니다.

[a-zA-Z] == \p{Alpha}, [0-9] == \p{Digit}, [ \t\n\x0B\f\r] == \p{Space} 등등... api에 자세히 나와있습니다.

 

다음으로 기호를 보겠습니다.

일단 .(쩜) 입니다.

.(쩜)은 하나의 문자를 나타냅니다. a.b 라는 패턴은 a랑 b사이에 하나의 문자가 꼭 있어야 한다는 패턴입니다.

a..b는 a랑 b사이에 꼭 두개의 문자가 있어야 한다는 패턴이 됩니다.

근데 우낀건 이 .(쩜) 자체를 나타낼려면 특수문자 이므로 \를 붙여줘야 하는데

이 .(쩜)이 [] 안에 쓰이면 즉 [.] == \. 이 되어버립니다. 즉 . != \. == [.] == [\.] 이라는 얘기지요

이유는 모르겠지만... [] 자체가 하나의 케릭터를 나타내기 때문에 [.]도 .(쩜) 문자로 취급을 하는 거 같습니다.

아까 위에서 a[.]b하면 a랑 b사이에 꼭 .(쩜) 문자가 있어야 한다는 패턴이라는 얘기지요. 즉 a/.b == a[.] 가 됩니다.

 

^ 문자는 문자열의 맨앞을 나타냅니다. ^Aeho 하면 문자열이 Aeho로 시작한다는 패턴이 됩니다.

이 ^가 []안에 쓰이면 not(!)의 의미를 같습니다. [^a-zA-Z] 는 영문자가 아니다 라는 패턴이 됩니다.

 

$ 문자는 문자열의 끝을 나타냅니다. Aeho$ 하면 문자열이 Aeho로 끝난다는 패턴이 됩니다.

 

| 문자는 or를 나타냅니다. |문자 자체를 나타낼려면 \|를 해야 합니다.

흔희 String 클래스의 split() 메서드가 제대로 안짤릴 때가 있다는 사람들이 있습니다.

그래서 StringTokenizer객체를 사용하고는 하던데요... 잘못된 정규식 사용 때문이라고 생각합니다.

split()은 인자로 정규식 패턴을 받고 StringTokenizer 는 실제 문자열을 구분자의 인자로 받습니다. 실재로 이들은 기능이 좀 다릅니다. 각각의 사용 용법이 다르다고 생각합니다. String.split()이 제대로 동작하지 않는다면 api 그것도 java.lang.String클래스에 멤서드로 등록이 되있을 수가 없을 것입니다...ㅋㅋ

 

"ab|cd|ef" 라는 문자열을 split("|") 하게되면 배열이 a,b,c,d,e,f 로 짤릴 것입니다. split("\\|") 하게되면 ab, cd, ef 로 짤릴 것입니다. 이유는 다들 잘 아실겁니다.

스플릿이 잘 짤릴 때도 있고 안될 때도 있다고 하시는 사람들은 대부분 그 구분자를 정규식에서 사용하는 특수

문자(대표적으로 |)를 사용할려고 하기때문에 또 그 때 \를 잘 사용을 하지 않아서 그런 경우라고 생각합니다.

 

String 클래스에 있는 trim() 메서드를 정규식으로 구현한다면...

public String trim() {
    return this.str.replaceAll("^\\p{Space}|\\p{Space}$", "");
} 정도가 되지 않을까 싶습니다. 아님 말고요...ㅋㅋ

 

다음은... 반복 횟수를 나타내는 기호들입니다.
* 기호는 앞에있는 패턴이 0번 이상 출현함을 나타냅니다. ".*" 은 모든 문자열을 나타냅니다.
+ 기호는 앞에있는 패턴이 1번 이상 출현함을 나타냅니다. {1,} 이 녀석이랑 같은 의미가 될 거 같습니다.
? 기호는 앞에있는 패턴이 0 or 1 번 출현함을 나타냅니다. {0, 1} 이 녀것이 되겠네요.

 

이 정도만 알면 정규식을 읽고 쓸 수 있었습니다....ㅋㅋ, 더이상 알고 싶지않습니다.

필요하다면 api에 자세히 나와있죠... 역시 공식지원이라 좋군요...ㅎㅎ

 

이 번에는 정규식 그룹을 보겠습니다. 그룹은 api 보면 설명이 나왔습니다만...
()의 중복된 순서를 나타냅니다. 예를 들어 (A)(B(C)) 이와같은 패턴이 있다면...괄호가 열려진 순서대로 그룹의 번호가 정해집니다. group(0) 번은 항상 패턴 전체를 나타냅니다. group(1)은 (A) 패턴입니다. group(2)은 (B(C)) 가 되고, group(3) 은 (C) 이 됩니다.

 

이 그룹은 java.util.regex.Matcher 클래스를 이용하여 사용할 수 있는데요...
예를 들어 어떤 문자열이 있는데... 그 전체 문자열 중에서 url 정보를 가져오고 나서 실제로 그 url의 프로토콜을 알아보고자 한다면 프로토콜 부분의 패턴을 ()로 묶어주면 group(1) 을 이용하여 가져올 수 있게 됩니다.

다른 쓸 말이 많지만... 일단 이 정도만 정리해 보겠습니다.
힘드네요... 헉헉...

[이 게시물은 하나를하더라도최선을님에 의해 2024-04-17 15:18:37 자유게시판에서 이동 됨]

댓글목록0

등록된 댓글이 없습니다.
게시판 전체검색