public:computer:regexp

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
Last revisionBoth sides next revision
public:computer:regexp [2021/08/23 18:27] alexpublic:computer:regexp [2023/01/01 00:56] – [참조 그룹] alex
Line 1: Line 1:
 ====== Regular Expressions ====== ====== Regular Expressions ======
-<lead>정규표현식은 특정 문자열을 가리키는 패턴이다. 즉 이 패턴으로 원하는 문자열을 찾는다.</lead> - 켄 톰슨+**정규표현식은 특정 문자열을 가리키는 패턴이다. 즉 이 패턴으로 원하는 문자열을 찾는다.** - 켄 톰슨
  
 ===== 기본 패턴 찾기 ===== ===== 기본 패턴 찾기 =====
Line 9: Line 9:
   * 수량자; {숫자}: 해당 갯수, {최소숫자,최대숫자}: 최소숫자부터 최대숫자 갯수만큼 , ?: 하나 이하, +: 하나 이상, *: 0 이상   * 수량자; {숫자}: 해당 갯수, {최소숫자,최대숫자}: 최소숫자부터 최대숫자 갯수만큼 , ?: 하나 이하, +: 하나 이상, *: 0 이상
   * 상수   * 상수
 +
 +^  정규표현식의 메타 문자  ^^^^
 +^ 메타 문자  ^ 이름  ^ 코드 포인트  ^ 의미  ^
 +^ .  | 점  | U+002E  | 임의의 문자를 찾음  |
 +^ \  | 역슬래시  | U+005C  | 문자의 특수 의미를 없앰  |
 +^ %%|%%  | 세로줄  | U+007C  | 선택  |
 +^ %%^%%  | 악센트 기호  | U+005E  | 행의 시작을 나타내는 앵커  |
 +^ $  | 달러 기호  | U+0024  | 행의 끝을 나타내는 앵커  |
 +^ ?  | 물음표  | U+003F  | 0번 또는 한 번을 나타내는 수량자  |
 +^ *  | 별표  | U+002A  | 0번 이상을 나타내는 수량자  |
 +^ +  | 덧셈 기호  | U+002B  | 한 번 이상을 나타내는 수량자  |
 +^ [  | 왼쪽 대괄호  | U+005B  | 문자 클래스 시작  |
 +^ ]  | 오른쪽 대괄호  | U+005D  | 문자 클래스 끝  |
 +^ {  | 왼쪽 중괄호  | U+007B  | 수량자 또는 블록 시작  |
 +^ }  | 오른쪽 중괄호  | U+007D  | 수량자 또는 블록 끝  |
 +^ (  | 왼쪽 소괄호  | U+0028  | 그룹 시작  |
 +^ )  | 오른쪽 소괄호  | U+0029  | 그룹 끝  |
 +
 +
  
 ==== 숫자 ==== ==== 숫자 ====
Line 19: Line 38:
  
 ^  단축 문자((이 외에 더 있음, 정규표현식 엔진에 따라 지원 여부 다양))  ^^ ^  단축 문자((이 외에 더 있음, 정규표현식 엔진에 따라 지원 여부 다양))  ^^
 +^ 단축문자  ^ 설명  ^
 ^ \a  | 벨 문자  | ^ \a  | 벨 문자  |
 ^ [\b]  | 백스페이스 문자  | ^ [\b]  | 백스페이스 문자  |
Line 46: Line 66:
  
 ==== 임의의 문자 ==== ==== 임의의 문자 ====
-  * . (U+002E); 개행 문자((유닉스에서는 \n(U+0004), 윈도우에서는 \n과\r(U+000D)))를 제외한 모든 문자+  * . (U+002E); 개행 문자(( 유닉스에서는 \n(U+0004), 윈도우에서는 \n과\r(U+000D) ))를 제외한 모든 문자
   * \b; 단어의 경계   * \b; 단어의 경계
  
 ==== 참조 그룹 ==== ==== 참조 그룹 ====
-  * 찾고자 하는 내용을 ()로 감싼 후(참조) $1, $2 혹은 \1, \2와 같이 역참조+  * 찾고자 하는 내용을 ()로 감싼 후(참조) \$1, \$2 혹은 \1, \2와 같이 역참조
  
  
Line 67: Line 87:
   * \A; ^의 기능처럼 해당 패턴이 행의 시작 위치에 나오는지 찾는다. PCRE(Perl Compatible Regular Expression)   * \A; ^의 기능처럼 해당 패턴이 행의 시작 위치에 나오는지 찾는다. PCRE(Perl Compatible Regular Expression)
   * \Z, \z; 해당 패턴이 행의 끝에 나오는지   * \Z, \z; 해당 패턴이 행의 끝에 나오는지
-  * +  * \Q문자\E; 문자열을 상수로 지정
  
 ===== 선택, 그룹, 역참조 ===== ===== 선택, 그룹, 역참조 =====
 +  * 그룹; 텍스트를 괄호로 묶은 것
 +    * 두 가지 이상의 패턴 중 하나를 선택할 때
 +    * 서브패턴을 만들 때
 +    * 나중에 역참조하기 위해 참조 그룹을 지정할 때
 +    * 수량자 같이 그룹으로 묶은 패턴에 어떤 작업을 적용할 때
 +    * 비참조 그룹을 사용할 때
 +    * 원자 그룹을 만들 때(고급과정)
 +  * 선택 alternation; 찾고자 하는 패턴을 선택
 +
 +^  정규표현식 옵션((서브패턴 이름 지정은 http://www.pcre.org/pcre.txt 참고))  ^^^
 +^ 옵션  ^ 설명  ^ 지원  ^
 +^ (?d)  | 유닉스 행  | 자바  |
 +^ (?i)  | 대소문자 구분 없앰  | PCRE, Perl, 자바  |
 +^ (iJ)  | 이름 반복 허용  | PCRE*  |
 +^ (?m)  | 다중 행  | PCRE, Perl, 자바  |
 +^ (?s)  | 한 행(dotall)  | PCRE, Perl, 자바  |
 +^ (?u)  | 유니코드  | 자바  |
 +^ (?U)  | 욕심쟁이 모드 해제  | PCRE  |
 +^ (?x)  | 공백과 코멘트는 무시  | PCRE, Perl, 자바  |
 +^ (?-...)  | 옵션 기능 제거  | PCRE  |
 +
 +^  Perl 변경자(플래그)((http://perldoc.perl.org/perlre.html#Modifiers 참고))  ^^
 +^ 변경자  ^ 설명  ^
 +^ a  | \d, \s, \w 및 ASCII 범위 내의 POSIX 문자  |
 +^ c  | 찾기 실패 후 현재 위치 유지  |
 +^ d  | 현재 플랫폼의 기본 설정 사용  |
 +^ g  | global 모드 설정  |
 +^ i  | 대소문자 구분 없앰  |
 +^ l  | 현재 로케일 설정 사용  |
 +^ m  | 다중 행 문자열  |
 +^ p  | 찾은 문자열을 저장  |
 +^ s  | 문자열을 한 행으로 간주  |
 +^ u  | 유니코드 규칙 사용  |
 +^ x  | 공백과 코멘트 무시  |
 +
 +  * 서브패턴 ex) (the|The|THE), (t|T)h(e|eir)
 +  * 그룹 참조와 역참조; \1, $1 
 +  * 그룹 이름 지정; ?<one>, ?<two>
 +  * 그룹 이름으로 참조; $+{one}, $+{two}
 +
 +^  그룹 이름 지정 구문  ^^
 +^ 구문  ^ 설명  ^
 +^ (?<name>...)  | 그룹 이름 지정  |
 +^ (?name...)  | 또 다른 그룹 이름 지정  |
 +^ (?P<name>...)  | 파이썬에서 그룹 이름 지정  |
 +^ \k<name>  | Perl에서 이름으로 참조  |
 +^ \k'name'  | Perl에서 이름으로 참조  |
 +^ \g{name}  | Perl에서 이름으로 참조  |
 +^ \k{name}  | .NET에서 이름으로 참조  |
 +^ (?P=name)  | 파이썬에서 이름으로 참조  |
 +
 +  * 비참조 그룹; 역참조가 필요 없을 경우 ex) (?:the|The|THE), (?i)(?:the), (?:(?i)ther), (?i:the)
 +  * 원자 그룹; 비참조 그룹 중 하나. 백트래킹 backtracking을 하는 정규표현식 엔진을 사용하는 경우, 이 그룹을 사용하면 정규표현식 전체는 아니더라도 원자 그룹에 해당하는 부분의 백트래킹 기능을 없앰.
 +    * ex) (?>the)
  
 ===== 문자 클래스 ===== ===== 문자 클래스 =====
 +  * 대괄호식 bracketed expressions
 +  * [a-z], [A-Z], [aeiou], [0-9], ...
 +  * 부정 문자 클래스; [^문자]
 +  * 합집합; [0-3[6-9]]
 +  * 차집합; [a-z&&[^m-r]]
 +
 +==== POSIX 문자 클래스 ====
 +^  POSIX 문자 클래스  ^^
 +^ 문자 클래스  ^ 설명  ^
 +^ <nowiki>[[:alnum:]]</nowiki>  | 영문자와 숫자  |
 +^ <nowiki>[[:alpha:]]</nowiki>  | 알파벳 문자(영문자)  |
 +^ <nowiki>[[:ascii:]]</nowiki>  | ASCII 문자(모두 128)  |
 +^ <nowiki>[[:blank:]]</nowiki>  | 빈 문자  |
 +^ <nowiki>[[:ctrl:]]</nowiki>  | 제어 문자  |
 +^ <nowiki>[[:digit:]]</nowiki>  | 숫자  |
 +^ <nowiki>[[:graph:]]</nowiki>  | 그래픽 문자  |
 +^ <nowiki>[[:lower:]]</nowiki>  | 소문자  |
 +^ <nowiki>[[:print:]]</nowiki>  | 인쇄 가능한 문자  |
 +^ <nowiki>[[:punct:]]</nowiki>  | 구두점 문자  |
 +^ <nowiki>[[:space:]]</nowiki>  | 공백 문자  |
 +^ <nowiki>[[:upper:]]</nowiki>  | 대문자  |
 +^ <nowiki>[[:word:]]</nowiki>  | 단어  |
 +^ <nowiki>[[:xdigit:]]</nowiki>  | 16진수  |
 +
 +
  
 ===== 유니코드와 기타 문자 ===== ===== 유니코드와 기타 문자 =====
 +  * \u16진수코드; \u00e9, \xe9
 +  * 8진수로 문자 찾기; \351(==\u00e9)
 +  * 제어문자 찾기; /cx
 +
  
 ===== 수량자 ===== ===== 수량자 =====
 +  * 욕심많고, 게으르고, 독점적인 수량자
 +  * 욕심쟁이; 입력된 텍스트에서 가능한 많은 부분, 즉 전체 문자열을 가져온 다음 원하는 문자열을 찾아내려고 시도.
 +  * 게으른(또는 느슨한) 수량자; 우선 문자열의 시작 위치부터 검색. 원하는 문자열을 찾을 때까지 하나씩 문자를 증가시키면서 찾다가, 계속 찾지 못하면 마지막으로 전체 텍스트를 검사. 일반 수량자 뒤에 물음표(?)를 붙인다.
 +  * 독점적인 수량자; 전체 텍스트를 가져온 후, 찾고자 하는 문자열인지를 검사. 오직 한 번만 시도, 백트래킹은 하지 않음. 일반 수량자 뒤에 덧셈기호(+)를 붙인다.
 +  * 클리니 스타(*)
 +  * *, +, ?
 +
 +^  기본 수량자  ^^
 +^ 구문  ^ 설명  ^
 +^ ?  | 0 또는 하나  |
 +^ +  | 하나 이상  |
 +^ *  | 0 또는 그 이상  |
 +
 +^  게으른 수량자  ^^
 +^ 구문  ^ 설명  ^
 +^ ??  | 게으르게 0번 또는 한 번  |
 +^ +?  | 게으르게 한 번 이상  |
 +^ *?  | 게으르게 0번 이상  |
 +^ {n}?  | 게으르게 n번  |
 +^ {n.}?  | 게으르게 n번 이상  |
 +^ {m,n}?  | 게으르게 m부터 n까지  |
 +
 +^  독정적인 수량자  ^^
 +^ 구문  ^ 설명  ^
 +^ ?+  | 독점적으로 0번 또는 한 번  |
 +^ ++  | 독점적으로 한 번 이상  |
 +^ *+  | 독점적으로 0번 이상  |
 +^ {n}+  | 독점적으로 n번  |
 +^ {n.}+  | 독점적으로 n번 이상  |
 +^ {m,n}+  | 독점적으로 m에서 n까지  |
 +
 +
 +
 +===== 탐색 =====
 +  * lookaround
 +  * 긍정형 전방 탐색(Positive lookaheads)
 +  * 부정형 전방 탐색(Negative lookaheads)
 +  * 긍정형 후방 탐색(Positive lookbehinds)
 +  * 부정형 후방 탐색(Negative lookbehinds)
  
 ===== 자주 쓰는 정규표현식 ===== ===== 자주 쓰는 정규표현식 =====
Line 112: Line 254:
     - -가 2개 이상     - -가 2개 이상
     - >로 닫음      - >로 닫음 
 +
 +  * <del>이름 masking; <alert type="info"><nowiki>(JAVA) str.replaceFirst("(\\W)\\W+\$", "\$1*****"))</nowiki></alert></del>
 +  * 숫자를 제외한 모든 문자 제거; <alert type="info"><nowiki>(JAVA) strConverted = str.replaceAll("\\D", "");</nowiki></alert>
 +  * 숫자만으로 되어있는 사업자 번호 -> 사업자번호 형식; <alert type="info"><nowiki>(JAVA) strConverted = str.replaceFirst("(^\\d{3})(\\d{2})(\\d{5})\$", "\$1-\$2-\$3");</nowiki></alert>
 +  * 숫자만으로만 되어있는지 확인; <alert type="info"><nowiki>(JAVA) bDigitsOnly = str.matches("^\\d+\$");</nowiki></alert>
 +  * 첫글자만 보이게 마스킹; <alert type="info"><nowiki>(JAVA) strMasked = str.replaceFirst("(^\\S)\\S+\$", "\$1*****");</nowiki></alert>
 +  * Password Validataions (JAVA & TypeScript)<sxh java title:Password Validation for JAVA>
 +
 +    public static Boolean hasSpecialCharacter(String strPassword) 
 +    {
 +        Boolean bHasSpecialCharacter = Pattern.matches("^(?=.*[\\x21-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\x7e]).{1,}", strPassword);
 +
 +        if(true == bHasSpecialCharacter)
 +        {
 +            System.out.println(strPassword + " has Special Character.");
 +        }
 +        else
 +        {
 +            System.out.println(strPassword + " has no Special Character.");
 +        }
 +
 +        return bHasSpecialCharacter;
 +    }
 +
 +    public static Boolean isValidPassword(String strPassword) 
 +    {
 +        Boolean bValid = Pattern.matches("^(?=.*[a-zA-Z])(?=.*[0-9])(?=.*[\\x21-\\x2f|\\x3a-\\x40|\\x5b-\\x60|\\x7b-\\x7e]).{10,16}", strPassword);
 +
 +        System.out.println(strPassword + ":" + bValid);
 +        return bValid;
 +    }
 +
 +    public static Boolean hasAlphabet(String strPassword) 
 +    {
 +        Boolean bHasAlphabet = Pattern.matches("^(?=.*[a-zA-Z]).{1,}", strPassword);
 +
 +        if(true == bHasAlphabet) 
 +        {
 +            System.out.println(strPassword + " has Alphabet.");
 +        }
 +        else
 +        {
 +            System.out.println(strPassword + " has no Alphabet.");
 +        }
 +
 +        return bHasAlphabet;
 +    }
 +
 +    public static Boolean hasDigit(String strPassword)
 +    {
 +        Boolean bHasDigit = Pattern.matches("^(?=.*[\\d]).{1,}", strPassword);
 +
 +        if(true == bHasDigit)
 +        {
 +            System.out.println(strPassword + " has Digits.");
 +        }
 +        else
 +        {
 +            System.out.println(strPassword + " has no Digits.");
 +        }
 +
 +        return bHasDigit;
 +    }
 +
 +    public static void testPassword(String strPassword)
 +    {
 +        System.out.println("Your password is : " + strPassword);
 +
 +        hasAlphabet(strPassword);
 +        hasDigit(strPassword);
 +        hasSpecialCharacter(strPassword);
 +    }</sxh><sxh typescript title:Password Validation for TypeScript>
 +function hasAlphabet(strPassword: string) {
 +  const reg = new RegExp("^(?=.*[a-zA-Z]).{1,}$")
 +  const bHasAlphabet = reg.test(strPassword)
 +
 +  if(false === bHasAlphabet) {
 +    console.log(`${strPassword} has no alphabet.`)
 +  } else {
 +    console.log(`${strPassword} has alphabet.`)
 +  }
 +    
 +  return bHasAlphabet
 +}
 +
 +function hasDigit(strPassword: string) {
 +  const reg = new RegExp("^(?=.*[0-9]).{1,}$")
 +  const bHasDigit = reg.test(strPassword)
 +
 +  if(false === bHasDigit) {
 +    console.log(`${strPassword} has no digit.`)
 +  } else {
 +    console.log(`${strPassword} has digit.`)
 +  }
 +
 +  return bHasDigit
 +}
 +
 +function hasSpecialCharacter(strPassword: string) {
 +  const reg = new RegExp("^(?=.*[\\x21-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\x7e]).{1,}$")
 +  const bHasSpecialCharacter = reg.test(strPassword)
 +
 +  if(false === bHasSpecialCharacter){
 +    console.log(`${strPassword} has no special character.`)
 +  } else {
 +    console.log(`${strPassword} has special character.`)
 +  }
 +
 +  return bHasSpecialCharacter
 +}
 +
 +function isValidPassword(strPassword: string) {
 +  const reg = new RegExp("^(?=.*[a-zA-Z])(?=.*[0-9])(?=.*[\\x21-\\x2f|\\x3a-\\x40|\\x5b-\\x60|\\x7b-\\x7e]).{10,16}$")
 +  const bValid = reg.test(strPassword)
 +
 +  if(false === bValid) {
 +    console.log(`${strPassword} is invalid.`)
 +  } else {
 +    console.log(`${strPassword} is valid.`)
 +  }
 +
 +  return bValid
 +}
 +
 +function testPassword(strPassword: string) {
 +  console.log(`Your Password is : ${strPassword}`)
 +
 +  hasAlphabet(strPassword)
 +  hasDigit(strPassword)
 +  hasSpecialCharacter(strPassword)
 +
 +  isValidPassword(strPassword)
 +
 +}</sxh>
 +  * camelCase to snake_case and MACRO_CASE (JAVA)<sxh java title:camelCase to snake_case and MACRO_CASE for JAVA>
 +    public static String getSnakeCaseFromCamelCase(String strCamelCase)
 +    {
 +        return strCamelCase.replaceAll("([A-Z])", "_$1").toLowerCase();
 +    }
 +
 +    public static String getMacroCaseFromCamelCase(String strCamelCase) 
 +    {
 +        return strCamelCase.replaceAll("([A-Z])", "_$1").toUpperCase();
 +    }
 +</sxh>
 +  * Card Number Validation (TypeScript)<sxh typescript title:Card Number Validation Example for TypeScript>
 +function validateIBKCEOCard(strCardNumber: string) {
 +  const regDigitsOnly = /(\D+)/gi
 +  const strDigits = strCardNumber.replace(regDigitsOnly, "")
 +
 +  if (strDigits.length != 16) {
 +    console.log(strCardNumber + ' is invalid card number')
 +    return
 +  }
 +  
 +  console.log('validate IBK CEO Card: ' + strCardNumber + ' => ' + strDigits + '(' + strDigits.length + ')')
 +
 +  const regValidate: RegExp = /^943003|^552103\d+$/g
 +  const bValid = regValidate.test(strDigits)
 +
 +  console.log('is valid? ' + bValid)
 +}
 +</sxh>
 +
  
  
 ===== Tools ===== ===== Tools =====
 +
 +==== 프로그램과 라이브러리 ====
 +  * Perl
 +  * PCRE(Perl Compatible Regular Expression)
 +  * 루비에서 사용하는 오니구루마
 +  * 파이썬
 +  * RE2
 +
 +
 ==== On-line ==== ==== On-line ====
   * [[https://www.regexpal.com/|RegEx Pal]]   * [[https://www.regexpal.com/|RegEx Pal]]
   * [[https://regexr.com/|RegExr]]   * [[https://regexr.com/|RegExr]]
-  * +  * [[https://rubular.com/|Rubular]] 
 + 
 ==== Offline ==== ==== Offline ====
   * QED   * QED
Line 129: Line 446:
   * [[https://notepad-plus-plus.org/downloads/|Notepad++]] Windows   * [[https://notepad-plus-plus.org/downloads/|Notepad++]] Windows
   * [[https://www.oxygenxml.com/|Oxygen XML Editor]]   * [[https://www.oxygenxml.com/|Oxygen XML Editor]]
 +  * reggy
 +
 +
 +===== References =====
 +  * [[https://jamesdreaming.tistory.com/182|[ 자바 코딩 ] REGULAR EXPRESSION 정규표현식 - 숫자만 허용하기]]
 +  * [[https://coding-factory.tistory.com/529|[Java] 자바 정규 표현식 (Pattern, Matcher) 사용법 & 예제]]
 +  * [[https://developer.mozilla.org/ko/docs/Web/JavaScript/Guide/Regular_Expressions|정규 표현식]]
 +  * [[https://apiclass.tistory.com/entry/%EC%8B%A4%EC%A0%9C-%EC%82%AC%EC%9A%A9%ED%95%98%EB%8A%94-%EC%A0%95%EA%B7%9C%EC%8B%9D-%ED%8C%A8%ED%84%B4|실제 사용하는 정규식 패턴]]
 +  * [[https://intro0517.tistory.com/135|자바스크립트 정규식 정리(숫자만, 한글만, 메일, 전화번호, 비밀번호)]]
 +  * [[https://develop-sense.tistory.com/62|[JAVA] 정규식을 이용한 마스킹(정규표현식 마스킹 처리)]]
 +  * [[https://leejiheg.tistory.com/entry/%EC%A0%95%EA%B7%9C-%ED%91%9C%ED%98%84%EC%8B%9D-%EA%B8%B0%EB%B3%B8|정규 표현식 기본]]
 +  * [[https://youngjinmo.github.io/2020/01/reg/|정규표현식(Reg)]]
 +  * [[https://minj0i.tistory.com/26|[JAVA] 이름 마스킹처리]]
 +  * [[https://docs.oracle.com/javase/8/docs/api/java/util/regex/Pattern.html|Class Pattern]]
 +  * [[https://blog.naver.com/PostView.nhn?blogId=realuv&logNo=220699272999|[Javascript] 정규식을 이용한 특수문자, 한글 등 특정 문자 체크(제거)]]
 +
 +
 +
 +
 +
 +
  • public/computer/regexp.txt
  • Last modified: 2023/01/01 00:58
  • by alex