λ λΉ λ₯΄κ³ ν¨μ¨μ μΈ μ½λλ₯Ό μμ±νμΈμ. λ°±νΈλνΉλΆν° κ³ κΈ μμ§ νλκΉμ§ νμμ μΈ μ κ· ννμ μ΅μ ν κΈ°μ μ μμ보μΈμ.
μ κ· ννμ μ΅μ ν: Regex μ±λ₯ νλ μ¬μΈ΅ λΆμ
μ κ· ννμ, μ¦ regexλ νλ νλ‘κ·Έλλ¨Έμ ν΄ν·μμ μμ΄μλ μ λ λꡬμ λλ€. μ¬μ©μ μ λ ₯ μ ν¨μ± κ²μ¬, λ‘κ·Έ νμΌ νμ±λΆν° μ κ΅ν κ²μ λ° λ°κΎΈκΈ° μμ , λ°μ΄ν° μΆμΆμ μ΄λ₯΄κΈ°κΉμ§ κ·Έ νκ³Ό λ€μ¬λ€λ₯ν¨μ λΆμΈν μ μμ΅λλ€. νμ§λ§ μ΄ νμλ μ¨κ²¨μ§ λΉμ©μ΄ λ°λ¦ λλ€. μλͺ» μμ±λ regexλ μ‘°μ©ν μ±λ₯ μ νμ μμΈμ΄ λμ΄ μλΉν μ§μ°μ μ λ°νκ³ , CPU μ¬μ©λμ κΈμ¦μν€λ©°, μ΅μ μ κ²½μ° μ ν리μΌμ΄μ μ λ©μΆκ² ν μ μμ΅λλ€. λ°λ‘ μ΄ μ§μ μμ μ κ· ννμ μ΅μ νλ 'μμΌλ©΄ μ’μ' κΈ°μ μ΄ μλλΌ, κ²¬κ³ νκ³ νμ₯ κ°λ₯ν μννΈμ¨μ΄λ₯Ό ꡬμΆνκΈ° μν ν΅μ¬ κΈ°μ μ΄ λ©λλ€.
μ΄ μ’ ν© κ°μ΄λμμλ regex μ±λ₯μ μΈκ³λ₯Ό μ¬μΈ΅μ μΌλ‘ νꡬν κ²μ λλ€. μ°λ¦¬λ μ κ°λ¨ν΄ 보μ΄λ ν¨ν΄μ΄ μΉλͺ μ μΌλ‘ λλ €μ§ μ μλμ§ μμλ³΄κ³ , regex μμ§μ λ΄λΆ μλ λ°©μμ μ΄ν΄νλ©°, μ νν λΏλ§ μλλΌ λλΆμκ² λΉ λ₯Έ μ κ· ννμμ μμ±νκΈ° μν κ°λ ₯ν μμΉκ³Ό κΈ°μ λ€μ κ°μΆκ² λ κ²μ λλ€.
'μ΄μ ' μ΄ν΄νκΈ°: μλͺ»λ Regexμ λΉμ©
μ΅μ ν κΈ°μ μ μ΄ν΄λ³΄κΈ° μ μ, μ°λ¦¬κ° ν΄κ²°νλ €λ λ¬Έμ λ₯Ό μ΄ν΄νλ κ²μ΄ μ€μν©λλ€. μ κ· ννμκ³Ό κ΄λ ¨λ κ°μ₯ μ¬κ°ν μ±λ₯ λ¬Έμ λ μΉλͺ μ μΈ λ°±νΈλνΉ(Catastrophic Backtracking)μΌλ‘ μλ €μ Έ μμΌλ©°, μ΄λ μ κ· ννμ μλΉμ€ κ±°λΆ(ReDoS) μ·¨μ½μ μΌλ‘ μ΄μ΄μ§ μ μλ μνμ λλ€.
μΉλͺ μ μΈ λ°±νΈλνΉ(Catastrophic Backtracking)μ΄λ 무μμΈκ°?
μΉλͺ μ μΈ λ°±νΈλνΉμ μ κ·μ μμ§μ΄ λ§€μΉλ₯Ό μ°Ύκ±°λ (λλ λ§€μΉκ° λΆκ°λ₯νλ€κ³ νλ¨νλ λ°) λΉμ μμ μΌλ‘ μ€λ μκ°μ΄ 걸릴 λ λ°μν©λλ€. μ΄λ νΉμ μ νμ ν¨ν΄μ΄ νΉμ μ νμ μ λ ₯ λ¬Έμμ΄μ λν΄ μ€νλ λ λ°μν©λλ€. μμ§μ ν¨ν΄μ λ§μ‘±μν€κΈ° μν΄ κ°λ₯ν λͺ¨λ κ²½λ‘λ₯Ό μλνλ©° μ΄μ§λ¬μ΄ μμ΄μ λ―Έλ‘μ κ°νκ² λ©λλ€. λ¨κ³μ μλ μ λ ₯ λ¬Έμμ΄μ κΈΈμ΄μ λ°λΌ κΈ°νκΈμμ μΌλ‘ μ¦κ°νμ¬ μ ν리μΌμ΄μ μ΄ λ©μΆ κ²μ²λΌ 보μ΄κ² λ§λλλ€.
μ·¨μ½ν regexμ λνμ μΈ μλ λ€μκ³Ό κ°μ΅λλ€: ^(a+)+$
μ΄ ν¨ν΄μ μΆ©λΆν λ¨μν΄ λ³΄μ λλ€. νλ μ΄μμ 'a'λ‘ κ΅¬μ±λ λ¬Έμμ΄μ μ°Ύμ΅λλ€. "a", "aa", "aaaaa"μ κ°μ λ¬Έμμ΄μμλ μλ²½νκ² μλν©λλ€. λ¬Έμ λ "aaaaaaaaaaaaaaaaaaaaaaaaaaab"μ κ°μ΄ κ±°μ μΌμΉνμ§λ§ κ²°κ΅ μ€ν¨νλ λ¬Έμμ΄μ λν΄ ν μ€νΈν λ λ°μν©λλ€.
μ΄κ²μ΄ μ κ·Έλ κ² λλ¦°μ§μ λν μ΄μ λ λ€μκ³Ό κ°μ΅λλ€:
- λ°κΉ₯μͺ½
(...)+μ μμͺ½a+λ λͺ¨λ νμμ μλμ(greedy quantifier)μ λλ€. - μμͺ½
a+κ° λ¨Όμ 27κ°μ 'a'λ₯Ό λͺ¨λ λ§€μΉν©λλ€. - λ°κΉ₯μͺ½
(...)+λ μ΄ ν λ²μ λ§€μΉλ‘ λ§μ‘±ν©λλ€. - κ·Έλ° λ€μ μμ§μ λ¬Έμμ΄μ λ μ΅μ»€
$λ₯Ό λ§€μΉνλ €κ³ μλν©λλ€. 'b'κ° μκΈ° λλ¬Έμ μ€ν¨ν©λλ€. - μ΄μ μμ§μ λ°±νΈλ(backtrack)ν΄μΌ ν©λλ€. λ°κΉ₯μͺ½ κ·Έλ£Ήμ΄ λ¬Έμ νλλ₯Ό ν¬κΈ°νλ©΄, μμͺ½
a+λ μ΄μ 26κ°μ 'a'λ₯Ό λ§€μΉνκ³ , λ°κΉ₯μͺ½ κ·Έλ£Ήμ λ λ²μ§Έ λ°λ³΅μ΄ λ§μ§λ§ 'a'λ₯Ό λ§€μΉνλ €κ³ μλν©λλ€. μ΄κ² λν 'b'μμ μ€ν¨ν©λλ€. - μμ§μ μ΄μ μμͺ½
a+μ λ°κΉ₯μͺ½(...)+μ¬μ΄μ 'a' λ¬Έμμ΄μ λΆν νλ λͺ¨λ κ°λ₯ν λ°©λ²μ μλν κ²μ λλ€. Nκ°μ 'a'λ‘ μ΄λ£¨μ΄μ§ λ¬Έμμ΄μ κ²½μ°, μ΄λ₯Ό λΆν νλ λ°©λ²μ 2N-1κ°μ§κ° μμ΅λλ€. 볡μ‘λλ κΈ°νκΈμμ μ΄λ©° μ²λ¦¬ μκ°μ κΈκ²©ν μΉμμ΅λλ€.
μ΄ λ¨ νλμ, κ²λ³΄κΈ°μλ 무ν΄ν΄ 보μ΄λ regexκ° CPU μ½μ΄ νλλ₯Ό λͺ μ΄, λͺ λΆ, λλ κ·Έ μ΄μ λμ μ κ° λ€λ₯Έ νλ‘μΈμ€λ μ¬μ©μμ λν μλΉμ€λ₯Ό μ¬μ€μ κ±°λΆν μ μμ΅λλ€.
λ¬Έμ μ ν΅μ¬: Regex μμ§
regexλ₯Ό μ΅μ ννλ €λ©΄ μμ§μ΄ ν¨ν΄μ μ΄λ»κ² μ²λ¦¬νλμ§ μ΄ν΄ν΄μΌ ν©λλ€. regex μμ§μλ μ£Όλ‘ λ κ°μ§ μ νμ΄ μμΌλ©°, κ·Έ λ΄λΆ μλ λ°©μμ΄ μ±λ₯ νΉμ±μ κ²°μ ν©λλ€.
DFA (κ²°μ μ μ ν μ€ν λ§ν) μμ§
DFA μμ§μ regex μΈκ³μ μλκ΄μ
λλ€. μ΄λ€μ μ
λ ₯ λ¬Έμμ΄μ μΌμͺ½μμ μ€λ₯Έμͺ½μΌλ‘, ν λ²μ ν λ¬Έμμ© λ¨μΌ ν¨μ€λ‘ μ²λ¦¬ν©λλ€. μ΄λ€ μμ μμλ DFA μμ§μ νμ¬ λ¬Έμλ₯Ό κΈ°λ°μΌλ‘ λ€μ μνκ° λ¬΄μμΈμ§ μ νν μκ³ μμ΅λλ€. μ΄λ κ²°μ½ λ°±νΈλν νμκ° μμμ μλ―Έν©λλ€. μ²λ¦¬ μκ°μ μ νμ μ΄λ©° μ
λ ₯ λ¬Έμμ΄μ κΈΈμ΄μ μ λΉλ‘ν©λλ€. grep, awkμ κ°μ μ ν΅μ μΈ Unix λꡬλ€μ΄ DFA κΈ°λ° μμ§μ μ¬μ©νλ μμ
λλ€.
μ₯μ : κ·Ήλλ‘ λΉ λ₯΄κ³ μμΈ‘ κ°λ₯ν μ±λ₯. μΉλͺ μ μΈ λ°±νΈλνΉμ λ©΄μμ λλ€.
λ¨μ : μ νλ κΈ°λ₯ μ§ν©. λ°±νΈλνΉ λ₯λ ₯μ μμ‘΄νλ λ°±λ νΌλ°μ€(backreference), λλ¬λ³΄κΈ°(lookaround), μΊ‘μ² κ·Έλ£Ή(capturing group)κ³Ό κ°μ κ³ κΈ κΈ°λ₯μ μ§μνμ§ μμ΅λλ€.
NFA (λΉκ²°μ μ μ ν μ€ν λ§ν) μμ§
NFA μμ§μ Python, JavaScript, Java, C# (.NET), Ruby, PHP, Perlκ³Ό κ°μ νλ νλ‘κ·Έλλ° μΈμ΄μμ μ¬μ©λλ κ°μ₯ μΌλ°μ μΈ μ νμ
λλ€. μ΄λ€μ "ν¨ν΄ μ€μ¬μ "μ΄λ©°, μμ§μ΄ ν¨ν΄μ λ°λΌκ°λ©° λ¬Έμμ΄μ μ§νν©λλ€. λͺ¨νΈν μ§μ (μ: λ체 | λλ μλμ *, +)μ λλ¬νλ©΄ ν κ²½λ‘λ₯Ό μλν©λλ€. λ§μ½ κ·Έ κ²½λ‘κ° κ²°κ΅ μ€ν¨νλ©΄, λ§μ§λ§ κ²°μ μ§μ μΌλ‘ λ°±νΈλνμ¬ λ€μ κ°λ₯ν κ²½λ‘λ₯Ό μλν©λλ€.
μ΄ λ°±νΈλνΉ λ₯λ ₯μ NFA μμ§μ λ§€μ° κ°λ ₯νκ³ κΈ°λ₯μ΄ νλΆνκ² λ§λ€μ΄ λλ¬λ³΄κΈ° λ° λ°±λ νΌλ°μ€μ κ°μ 볡μ‘ν ν¨ν΄μ κ°λ₯νκ² ν©λλ€. κ·Έλ¬λ μ΄λ μΉλͺ μ μΈ λ°±νΈλνΉμ κ°λ₯νκ² νλ λ©μ»€λμ¦μ΄κΈ° λλ¬Έμ κ·Έλ€μ μν¬λ μ€κ±΄μ΄κΈ°λ ν©λλ€.
μ΄ κ°μ΄λμ λλ¨Έμ§ λΆλΆμμλ κ°λ°μλ€μ΄ κ°μ₯ μμ£Ό μ±λ₯ λ¬Έμ λ₯Ό κ²ͺλ NFA μμ§μ κΈΈλ€μ΄λ λ° μ΅μ ν κΈ°μ μ μ΄μ μ λ§μΆ κ²μ λλ€.
NFA μμ§μ μν ν΅μ¬ μ΅μ ν μμΉ
μ΄μ κ³ μ±λ₯ μ κ· ννμμ μμ±νλ λ° μ¬μ©ν μ μλ μ€μ©μ μ΄κ³ μ€ν κ°λ₯ν κΈ°μ λ€μ μ΄ν΄λ³΄κ² μ΅λλ€.
1. ꡬ체μ μΌλ‘ μμ±νκΈ°: μ λ°ν¨μ ν
κ°μ₯ νν μ±λ₯ μν°ν¨ν΄μ .*μ κ°μ μ§λμΉκ² μΌλ°μ μΈ μμΌλμΉ΄λλ₯Ό μ¬μ©νλ κ²μ
λλ€. μ (.)μ (κ±°μ) λͺ¨λ λ¬Έμμ μΌμΉνκ³ , λ³ν(*)λ "0λ² μ΄μ"μ μλ―Έν©λλ€. μ΄λ€μ΄ κ²°ν©λλ©΄ μμ§μκ² λ¬Έμμ΄μ λλ¨Έμ§ μ 체λ₯Ό νμμ μΌλ‘ μλΉν λ€μ, ν¨ν΄μ λλ¨Έμ§ λΆλΆμ΄ μΌμΉν μ μλμ§ νμΈνκΈ° μν΄ ν λ¬Έμμ© λ°±νΈλνλΌκ³ μ§μν©λλ€. μ΄λ λ§€μ° λΉν¨μ¨μ μ
λλ€.
λμ μ (HTML μ λͺ© νμ±):
<title>.*</title>
ν° HTML λ¬Έμμ λν΄ .*λ λ¨Όμ νμΌ λκΉμ§ λͺ¨λ κ²μ λ§€μΉν κ²μ
λλ€. κ·Έλ° λ€μ λ§μ§λ§ </title>λ₯Ό μ°Ύμ λκΉμ§ λ¬Έμ λ¨μλ‘ λ°±νΈλν©λλ€. μ΄κ²μ λΆνμν μμ
μ΄ λ§€μ° λ§μ΅λλ€.
μ’μ μ (λΆμ λ¬Έμ ν΄λμ€ μ¬μ©):
<title>[^<]*</title>
μ΄ λ²μ μ ν¨μ¬ λ ν¨μ¨μ μ
λλ€. λΆμ λ¬Έμ ν΄λμ€ [^<]*λ "'<'κ° μλ λͺ¨λ λ¬Έμλ₯Ό 0λ² μ΄μ λ§€μΉ"νλΌλ μλ―Έμ
λλ€. μμ§μ 첫 λ²μ§Έ '<'λ₯Ό λ§λ λκΉμ§ λ¬Έμλ₯Ό μλΉνλ©° μμΌλ‘ λμκ°λλ€. κ²°μ½ λ°±νΈλν νμκ° μμ΅λλ€. μ΄κ²μ μ§μ μ μ΄κ³ λͺ¨νΈνμ§ μμ μ§μμ΄λ©° μμ²λ μ±λ₯ ν₯μμ κ°μ Έμ΅λλ€.
2. νμ(Greed) λ κ²μΌλ¦(Laziness) λ§μ€ν°νκΈ°: λ¬Όμνμ ν
regexμ μλμλ κΈ°λ³Έμ μΌλ‘ νμμ (greedy)μ λλ€. μ΄λ μ 체 ν¨ν΄μ΄ μΌμΉν μ μλ ν κ°μ₯ λ§μ ν μ€νΈλ₯Ό μΌμΉμν¨λ€λ μλ―Έμ λλ€.
- νμμ :
*,+,?,{n,m}
μλμ λ€μ λ¬Όμνλ₯Ό μΆκ°νμ¬ λͺ¨λ μλμλ₯Ό κ²μΌλ₯΄κ²(lazy) λ§λ€ μ μμ΅λλ€. κ²μΌλ₯Έ μλμλ κ°λ₯ν ν μ μ ν μ€νΈλ₯Ό μΌμΉμν΅λλ€.
- κ²μΌλ₯Έ:
*?,+?,??,{n,m}?
μ: λ³Όλ νκ·Έ λ§€μΉ
μ
λ ₯ λ¬Έμμ΄: <b>First</b> and <b>Second</b>
- νμμ ν¨ν΄:
<b>.*</b>
μ΄κ²μ<b>First</b> and <b>Second</b>μ λ§€μΉλ©λλ€..*κ° λ§μ§λ§</b>κΉμ§ λͺ¨λ κ²μ νμμ μΌλ‘ μλΉνμ΅λλ€. - κ²μΌλ₯Έ ν¨ν΄:
<b>.*?</b>
μ΄κ²μ 첫 λ²μ§Έ μλμμ<b>First</b>μ λ§€μΉλκ³ , λ€μ κ²μνλ©΄<b>Second</b>μ λ§€μΉλ©λλ€..*?λ ν¨ν΄μ λλ¨Έμ§ λΆλΆ(</b>)μ΄ λ§€μΉλ μ μλλ‘ νμν μ΅μνμ λ¬Έμ μλ§ λ§€μΉνμ΅λλ€.
κ²μΌλ¦μ΄ νΉμ λ§€μΉ λ¬Έμ λ₯Ό ν΄κ²°ν μλ μμ§λ§, μ±λ₯μ μν λ§λ³ν΅μΉμ½μ μλλλ€. κ²μΌλ₯Έ λ§€μΉμ κ° λ¨κ³μμ μμ§μ ν¨ν΄μ λ€μ λΆλΆμ΄ μΌμΉνλμ§ νμΈν΄μΌ ν©λλ€. λ§€μ° κ΅¬μ²΄μ μΈ ν¨ν΄(μ΄μ ν¬μΈνΈμ λΆμ λ¬Έμ ν΄λμ€μ²λΌ)μ΄ μ’ μ’ κ²μΌλ₯Έ ν¨ν΄λ³΄λ€ λΉ λ¦ λλ€.
μ±λ₯ μμ (κ°μ₯ λΉ λ₯Έ μμλλ‘):
- ꡬ체μ μΈ/λΆμ λ¬Έμ ν΄λμ€:
<b>[^<]*</b> - κ²μΌλ₯Έ μλμ:
<b>.*?</b> - λ§μ λ°±νΈλνΉμ νλ νμμ μλμ:
<b>.*</b>
3. μΉλͺ μ μΈ λ°±νΈλνΉ νΌνκΈ°: μ€μ²©λ μλμ κΈΈλ€μ΄κΈ°
μ΄κΈ° μμ μμ 보μλ―μ΄, μΉλͺ μ μΈ λ°±νΈλνΉμ μ§μ μ μΈ μμΈμ μλνλ κ·Έλ£Ήμ΄ λμΌν ν μ€νΈλ₯Ό λ§€μΉν μ μλ λ λ€λ₯Έ μλμλ₯Ό ν¬ν¨νλ ν¨ν΄μ λλ€. μμ§μ μ λ ₯ λ¬Έμμ΄μ λΆν νλ μ¬λ¬ λ°©λ²μ΄ μλ λͺ¨νΈν μν©μ μ§λ©΄νκ² λ©λλ€.
λ¬Έμ κ° μλ ν¨ν΄:
(a+)+(a*)*(a|aa)+- μ
λ ₯ λ¬Έμμ΄μ λ§μ 'a'μ 'b'κ° ν¬ν¨λ κ²½μ°μ
(a|b)*
ν΄κ²°μ± μ ν¨ν΄μ λͺ¨νΈνμ§ μκ² λ§λλ κ²μ λλ€. μ£Όμ΄μ§ λ¬Έμμ΄μ μμ§μ΄ λ§€μΉν μ μλ λ°©λ²μ΄ λ¨ νλλΏμ΄λλ‘ ν΄μΌ ν©λλ€.
4. μμ κ·Έλ£Ήκ³Ό μμ μλμ νμ©νκΈ°
μ΄κ²μ ννμμμ λ°±νΈλνΉμ μ κ±°νλ κ°μ₯ κ°λ ₯ν κΈ°μ μ€ νλμ λλ€. μμ κ·Έλ£Ήκ³Ό μμ μλμλ μμ§μκ² "μΌλ¨ ν¨ν΄μ μ΄ λΆλΆμ λ§€μΉνλ€λ©΄, κ·Έ λ¬Έμλ€μ μ λ λλλ €μ£Όμ§ λ§λΌ. μ΄ ννμ μμΌλ‘ λ°±νΈλνμ§ λ§λΌ"κ³ λ§ν©λλ€.
μμ μλμ(Possessive Quantifiers)
μμ μλμλ μΌλ° μλμ λ€μ +λ₯Ό μΆκ°νμ¬ λ§λλλ€(μ: *+, ++, ?+, {n,m}+). Java, PCRE(PHP, R), Rubyμ κ°μ μμ§μμ μ§μλ©λλ€.
μ: μ«μ λ€μ 'a'κ° μ€λ κ²½μ° λ§€μΉ
μ
λ ₯ λ¬Έμμ΄: 12345
- μΌλ° Regex:
\d+a\d+κ° "12345"λ₯Ό λ§€μΉν©λλ€. κ·Έλ° λ€μ μμ§μ 'a'λ₯Ό λ§€μΉνλ €λ€ μ€ν¨ν©λλ€. λ°±νΈλνμ¬\d+κ° μ΄μ "1234"λ₯Ό λ§€μΉνκ³ , '5'μ λν΄ 'a'λ₯Ό λ§€μΉνλ €κ³ μλν©λλ€.\d+κ° λͺ¨λ λ¬Έμλ₯Ό ν¬κΈ°ν λκΉμ§ μ΄κ²μ κ³μν©λλ€. μ€ν¨νκΈ° μν΄ λ§μ μμ μ ν©λλ€. - μμ Regex:
\d++a\d++κ° μμ μ μΌλ‘ "12345"λ₯Ό λ§€μΉν©λλ€. μμ§μ 'a'λ₯Ό λ§€μΉνλ €λ€ μ€ν¨ν©λλ€. μλμκ° μμ μ μ΄μκΈ° λλ¬Έμ μμ§μ\d++λΆλΆμΌλ‘ λ°±νΈλνλ κ²μ΄ κΈμ§λ©λλ€. μ¦μ μ€ν¨ν©λλ€. μ΄κ²μ 'λΉ λ₯Έ μ€ν¨(failing fast)'λΌκ³ νλ©° λ§€μ° ν¨μ¨μ μ λλ€.
μμ κ·Έλ£Ή(Atomic Groups)
μμ κ·Έλ£Ήμ (?>...) ꡬ문μ κ°μ§λ©° μμ μλμλ³΄λ€ λ λ리 μ§μλ©λλ€(μ: .NET, Pythonμ μλ‘μ΄ `regex` λͺ¨λ). μ΄κ²λ€μ μμ μλμμ λκ°μ΄ μλνμ§λ§ μ 체 κ·Έλ£Ήμ μ μ©λ©λλ€.
(?>\d+)aλΌλ regexλ \d++aμ κΈ°λ₯μ μΌλ‘ λμΌν©λλ€. μμ κ·Έλ£Ήμ μ¬μ©νμ¬ μλμ μΉλͺ
μ μΈ λ°±νΈλνΉ λ¬Έμ λ₯Ό ν΄κ²°ν μ μμ΅λλ€:
μλ λ¬Έμ : (a+)+
μμμ ν΄κ²°μ±
: ((?>a+))+
μ΄μ λ΄λΆ κ·Έλ£Ή (?>a+)κ° 'a'μ μνμ€λ₯Ό λ§€μΉνλ©΄, μΈλΆ κ·Έλ£Ήμ΄ μ¬μλνλλ‘ μ λ κ·Έκ²λ€μ ν¬κΈ°νμ§ μμ κ²μ
λλ€. μ΄λ λͺ¨νΈμ±μ μ κ±°νκ³ κΈ°νκΈμμ μΈ λ°±νΈλνΉμ λ°©μ§ν©λλ€.
5. λ체(Alternation)μ μμκ° μ€μν©λλ€
NFA μμ§μ΄ λ체(`|` νμ΄ν μ¬μ©)λ₯Ό λ§λλ©΄ μΌμͺ½μμ μ€λ₯Έμͺ½μΌλ‘ λμμ μλν©λλ€. μ΄λ κ°μ₯ κ°λ₯μ±μ΄ λμ λμμ λ¨Όμ λ°°μΉν΄μΌ ν¨μ μλ―Έν©λλ€.
μ: λͺ λ Ήμ΄ νμ±
λͺ λ Ήμ΄λ₯Ό νμ±νκ³ μλλ°, `GET` λͺ λ Ήμ΄κ° 80%μ μκ°, `SET`μ΄ 15%, `DELETE`κ° 5%μ μκ° λμ λνλλ€κ³ κ°μ ν΄ λ΄ μλ€.
λ ν¨μ¨μ : ^(DELETE|SET|GET)
μ
λ ₯μ 80%μ λν΄ μμ§μ λ¨Όμ `DELETE`λ₯Ό λ§€μΉνλ €λ€ μ€ν¨νκ³ , λ°±νΈλνκ³ , `SET`μ λ§€μΉνλ €λ€ μ€ν¨νκ³ , λ°±νΈλν ν λ§μ§λ§μΌλ‘ `GET`μΌλ‘ μ±κ³΅ν κ²μ
λλ€.
λ ν¨μ¨μ : ^(GET|SET|DELETE)
μ΄μ 80%μ κ²½μ°μ μμ§μ 첫 λ²μ§Έ μλμμ λ§€μΉλ₯Ό μ»μ΅λλ€. μ΄ μμ λ³νλ μλ°±λ§ μ€μ μ²λ¦¬ν λ λμ λλ μν₯μ λ―ΈμΉ μ μμ΅λλ€.
6. μΊ‘μ²κ° νμ μμ λλ λΉμΊ‘μ² κ·Έλ£Ή μ¬μ©νκΈ°
regexμ κ΄νΈ (...)λ λ κ°μ§ μΌμ ν©λλ€: νμ ν¨ν΄μ κ·Έλ£Ήννκ³ , κ·Έ νμ ν¨ν΄κ³Ό μΌμΉν ν
μ€νΈλ₯Ό μΊ‘μ²ν©λλ€. μ΄ μΊ‘μ²λ ν
μ€νΈλ λμ€μ μ¬μ©νκΈ° μν΄ λ©λͺ¨λ¦¬μ μ μ₯λ©λλ€(μ: `\1`κ³Ό κ°μ λ°±λ νΌλ°μ€ λλ νΈμΆ μ½λμ μν μΆμΆ). μ΄ μ μ₯μλ μμ§λ§ μΈ‘μ κ°λ₯ν μ€λ²ν€λκ° μμ΅λλ€.
κ·Έλ£Ήν λμλ§ νμνκ³ ν
μ€νΈλ₯Ό μΊ‘μ²ν νμκ° μλ€λ©΄ λΉμΊ‘μ² κ·Έλ£Ήμ μ¬μ©νμμμ€: (?:...).
μΊ‘μ²λ§: (https?|ftp)://([^/]+)
μ΄κ²μ "http"μ λλ©μΈ μ΄λ¦μ λ³λλ‘ μΊ‘μ²ν©λλ€.
λΉμΊ‘μ²λ§: (?:https?|ftp)://([^/]+)
μ¬κΈ°μλ `https?|ftp`λ₯Ό μ¬μ ν κ·Έλ£Ήννμ¬ `://`κ° μ¬λ°λ₯΄κ² μ μ©λλλ‘ νμ§λ§, λ§€μΉλ νλ‘ν μ½μ μ μ₯νμ§ μμ΅λλ€. λλ©μΈ μ΄λ¦(κ·Έλ£Ή 1μ μμ)λ§ μΆμΆνλ λ° κ΄μ¬μ΄ μλ€λ©΄ μ΄κ²μ΄ μ½κ° λ ν¨μ¨μ μ
λλ€.
κ³ κΈ κΈ°μ λ° μμ§λ³ ν
λλ¬λ³΄κΈ°(Lookarounds): κ°λ ₯νμ§λ§ μ μ€νκ² μ¬μ©ν΄μΌ ν©λλ€
λλ¬λ³΄κΈ°(μ λ°©νμ (?=...), (?!...) λ° νλ°©νμ (?<=...), (?)λ λλΉκ° μλ λ¨μΈ(zero-width assertion)μ
λλ€. μ΄λ€μ μ€μ λ‘ λ¬Έμλ₯Ό μλΉνμ§ μκ³ μ‘°κ±΄μ νμΈν©λλ€. μ΄κ²μ 컨ν
μ€νΈλ₯Ό κ²μ¦νλ λ° λ§€μ° ν¨μ¨μ μΌ μ μμ΅λλ€.
μ: λΉλ°λ²νΈ μ ν¨μ± κ²μ¬
μ«μλ₯Ό ν¬ν¨ν΄μΌ νλ λΉλ°λ²νΈλ₯Ό κ²μ¦νλ regex:
^(?=.*\d).{8,}$
μ΄κ²μ λ§€μ° ν¨μ¨μ μ
λλ€. μ λ°©νμ (?=.*\d)λ μμΌλ‘ μ€μΊνμ¬ μ«μκ° μ‘΄μ¬νλμ§ νμΈν λ€μ 컀μλ₯Ό μμμΌλ‘ μ¬μ€μ ν©λλ€. ν¨ν΄μ μ£Όμ λΆλΆμΈ .{8,}λ λ¨μν 8μ μ΄μμ λ§€μΉνκΈ°λ§ νλ©΄ λ©λλ€. μ΄κ²μ μ’
μ’
λ 볡μ‘ν λ¨μΌ κ²½λ‘ ν¨ν΄λ³΄λ€ λ«μ΅λλ€.
μ¬μ κ³μ° λ° μ»΄νμΌ
λλΆλΆμ νλ‘κ·Έλλ° μΈμ΄λ μ κ· ννμμ "μ»΄νμΌ"νλ λ°©λ²μ μ 곡ν©λλ€. μ΄λ μμ§μ΄ ν¨ν΄ λ¬Έμμ΄μ ν λ² νμ±νκ³ μ΅μ νλ λ΄λΆ ννμ μμ±νλ€λ κ²μ μλ―Έν©λλ€. λμΌν regexλ₯Ό μ¬λ¬ λ² μ¬μ©νλ κ²½μ°(μ: 루ν λ΄λΆ), νμ 루ν μΈλΆμμ ν λ² μ»΄νμΌν΄μΌ ν©λλ€.
Python μμ :
import re
# regexλ₯Ό ν λ² μ»΄νμΌν©λλ€
log_pattern = re.compile(r'(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})')
for line in log_file:
# μ»΄νμΌλ κ°μ²΄λ₯Ό μ¬μ©ν©λλ€
match = log_pattern.search(line)
if match:
print(match.group(1))
μ΄κ²μ νμ§ μμΌλ©΄ μμ§μ΄ λ§€ λ°λ³΅λ§λ€ λ¬Έμμ΄ ν¨ν΄μ λ€μ νμ±ν΄μΌ νλ―λ‘ μλΉν CPU μ¬μ΄ν΄ λλΉμ λλ€.
Regex νλ‘νμΌλ§ λ° λλ²κΉ μ μν μ€μ©μ μΈ λꡬ
μ΄λ‘ μ νλ₯νμ§λ§, 보λ κ²μ΄ λ―Ώλ κ²μ λλ€. νλμ μΈ μ¨λΌμΈ regex ν μ€ν°λ μ±λ₯μ μ΄ν΄νλ λ° λ§€μ° κ·μ€ν λꡬμ λλ€.
regex101.comκ³Ό κ°μ μΉμ¬μ΄νΈλ "Regex λλ²κ±°" λλ "λ¨κ³λ³ μ€λͺ " κΈ°λ₯μ μ 곡ν©λλ€. regexμ ν μ€νΈ λ¬Έμμ΄μ λΆμ¬λ£μΌλ©΄ NFA μμ§μ΄ λ¬Έμμ΄μ μ²λ¦¬νλ λ°©λ²μ λν λ¨κ³λ³ μΆμ μ μ 곡ν©λλ€. λͺ¨λ λ§€μΉ μλ, μ€ν¨ λ° λ°±νΈλμ λͺ μμ μΌλ‘ 보μ¬μ€λλ€. μ΄κ²μ μ λΉμ μ regexκ° λλ¦°μ§ μκ°ννκ³ μ°λ¦¬κ° λ Όμν μ΅μ νμ μν₯μ ν μ€νΈνλ κ°μ₯ μ’μ λ°©λ²μ λλ€.
Regex μ΅μ νλ₯Ό μν μ€μ©μ μΈ μ²΄ν¬λ¦¬μ€νΈ
볡μ‘ν regexλ₯Ό λ°°ν¬νκΈ° μ μ μ΄ μ μ μ 체ν¬λ¦¬μ€νΈλ₯Ό ν΅ν΄ μ€νν΄ λ³΄μΈμ:
- ꡬ체μ±: λ λΉ λ₯΄κ³ μμ ν
[^"\r\n]*μ κ°μ λ ꡬ체μ μΈ λΆμ λ¬Έμ ν΄λμ€λ₯Ό μ¬μ©ν μ μλ κ³³μ κ²μΌλ₯Έ.*?λ νμμ μΈ.*λ₯Ό μ¬μ©νμ΅λκΉ? - λ°±νΈλνΉ:
(a+)+μ κ°μ μ€μ²©λ μλμκ° μμ΅λκΉ? νΉμ μ λ ₯μ λν΄ μΉλͺ μ μΈ λ°±νΈλνΉμΌλ‘ μ΄μ΄μ§ μ μλ λͺ¨νΈν¨μ΄ μμ΅λκΉ? - μμ μ±: μ¬νκ°λμ΄μλ μ λλ€κ³ μκ³ μλ νμ ν¨ν΄μΌλ‘μ λ°±νΈλνΉμ λ°©μ§νκΈ° μν΄ μμ κ·Έλ£Ή
(?>...)μ΄λ μμ μλμ*+λ₯Ό μ¬μ©ν μ μμ΅λκΉ? - λ체: μ
(a|b|c)λ체μμ κ°μ₯ νν λμμ΄ λ¨Όμ λμ΄λμ΄ μμ΅λκΉ? - μΊ‘μ²λ§: λͺ¨λ μΊ‘μ²λ§ κ·Έλ£Ήμ΄ νμν©λκΉ? μΌλΆλ₯Ό λΉμΊ‘μ² κ·Έλ£Ή
(?:...)μΌλ‘ λ³ννμ¬ μ€λ²ν€λλ₯Ό μ€μΌ μ μμ΅λκΉ? - μ»΄νμΌ: μ΄ regexλ₯Ό 루νμμ μ¬μ©νκ³ μλ€λ©΄, 미리 μ»΄νμΌνκ³ μμ΅λκΉ?
μ¬λ‘ μ°κ΅¬: λ‘κ·Έ νμ μ΅μ ν
λͺ¨λ κ²μ μ’ ν©ν΄ λ΄ μλ€. νμ€ μΉ μλ² λ‘κ·Έ λΌμΈμ νμ±νλ€κ³ μμν΄ λ³΄μΈμ.
λ‘κ·Έ λΌμΈ: 127.0.0.1 - - [10/Oct/2000:13:55:36 -0700] "GET /apache_pb.gif HTTP/1.0" 200 2326
μ΄μ (λλ¦° Regex):
^(\S+) (\S+) (\S+) \[(.*)\] "(.*)" (\d+) (\d+)$
μ΄ ν¨ν΄μ κΈ°λ₯μ μ΄μ§λ§ λΉν¨μ¨μ μ
λλ€. λ μ§μ μμ² λ¬Έμμ΄μ λν (.*)λ νΉν νμμ΄ μλͺ»λ λ‘κ·Έ λΌμΈμ΄ μμ κ²½μ° μλΉν λ°±νΈλνΉμ μ λ°ν©λλ€.
μ΄ν (μ΅μ νλ Regex):
^(\S+) (\S+) (\S+) \[[^\]]+\] "(?:GET|POST|HEAD) ([^ "]+) HTTP/[\d.]+" (\d{3}) (\d+)$
κ°μ μ¬ν μ€λͺ :
\[(.*)\]κ°\[[^\]]+\]λ‘ λ³κ²½λμμ΅λλ€. μΌλ°μ μ΄κ³ λ°±νΈλνΉνλ.*λ₯Ό λ«λ λκ΄νΈλ₯Ό μ μΈν λͺ¨λ κ²μ λ§€μΉνλ λ§€μ° κ΅¬μ²΄μ μΈ λΆμ λ¬Έμ ν΄λμ€λ‘ λ체νμ΅λλ€. λ°±νΈλνΉμ΄ νμ μμ΅λλ€."(.*)"κ°"(?:GET|POST|HEAD) ([^ "]+) HTTP/[\d.]+"λ‘ λ³κ²½λμμ΅λλ€. μ΄κ²μ μμ²λ κ°μ μ λλ€.- μ°λ¦¬κ° μμνλ HTTP λ©μλλ₯Ό λΉμΊ‘μ² κ·Έλ£Ήμ μ¬μ©νμ¬ λͺ μμ μΌλ‘ μ§μ νμ΅λλ€.
- μΌλ°μ μΈ μμΌλμΉ΄λ λμ
[^ "]+(곡백μ΄λ λ°μ΄νκ° μλ νλ μ΄μμ λ¬Έμ)λ‘ URL κ²½λ‘λ₯Ό λ§€μΉν©λλ€. - HTTP νλ‘ν μ½ νμμ μ§μ νμ΅λλ€.
- μν μ½λμ λν
(\d+)λ HTTP μν μ½λκ° νμ μΈ μ리μ΄λ―λ‘(\d{3})μΌλ‘ κ°νλμμ΅λλ€.
'μ΄ν' λ²μ μ κ·Ήμ μΌλ‘ λΉ λ₯΄κ³ ReDoS 곡격μΌλ‘λΆν° λ μμ ν λΏλ§ μλλΌ, λ‘κ·Έ λΌμΈμ νμμ λ μ격νκ² κ²μ¦νκΈ° λλ¬Έμ λ κ²¬κ³ ν©λλ€.
κ²°λ‘
μ κ· ννμμ μλ μ κ²μ λλ€. μ μ€ν¨κ³Ό μ§μμ κ°μ§κ³ μ¬μ©νλ©΄ 볡μ‘ν ν μ€νΈ μ²λ¦¬ λ¬Έμ μ λν μ°μν ν΄κ²°μ± μ λλ€. λΆμ£Όμνκ² μ¬μ©νλ©΄ μ±λ₯μ μ λͺ½μ΄ λ μ μμ΅λλ€. ν΅μ¬μ NFA μμ§μ λ°±νΈλνΉ λ©μ»€λμ¦μ μΌλμ λκ³ κ°λ₯ν ν μμ£Ό μμ§μ λ¨μΌνκ³ λͺ¨νΈνμ§ μμ κ²½λ‘λ‘ μλ΄νλ ν¨ν΄μ μμ±νλ κ²μ λλ€.
ꡬ체μ μΌλ‘ μμ±νκ³ , νμκ³Ό κ²μΌλ¦μ μ₯λ¨μ μ μ΄ν΄νκ³ , μμ κ·Έλ£ΉμΌλ‘ λͺ¨νΈμ±μ μ κ±°νκ³ , ν¨ν΄μ ν μ€νΈνκΈ° μν΄ μ¬λ°λ₯Έ λꡬλ₯Ό μ¬μ©ν¨μΌλ‘μ¨, μ κ· ννμμ μ μ¬μ μΈ λΆμ±μμ μ½λμ κ°λ ₯νκ³ ν¨μ¨μ μΈ μμ°μΌλ‘ λ³νν μ μμ΅λλ€. μ€λλΆν° λΉμ μ regexλ₯Ό νλ‘νμΌλ§νμ¬ λ λΉ λ₯΄κ³ μ λ’°ν μ μλ μ ν리μΌμ΄μ μ λ§λμΈμ.