KR_RegularExpression - somaz94/python-study GitHub Wiki

Python ์ •๊ทœํ‘œํ˜„์‹ ๊ฐœ๋… ์ •๋ฆฌ


1๏ธโƒฃ ๊ธฐ๋ณธ ํŒจํ„ด

์ •๊ทœํ‘œํ˜„์‹์˜ ๊ธฐ๋ณธ ํŒจํ„ด๋“ค์ด๋‹ค.

import re

# ๊ธฐ๋ณธ ๋งค์นญ
text = "Hello, World!"
match = re.search(r"World", text)
print(match.group())  # World

# ๋ฉ”ํƒ€๋ฌธ์ž ์‚ฌ์šฉ
pattern = r"\d+"  # ํ•˜๋‚˜ ์ด์ƒ์˜ ์ˆซ์ž
text = "There are 123 apples"
match = re.search(pattern, text)
print(match.group())  # 123

# ๋ฌธ์ž์—ด ์‹œ์ž‘๊ณผ ๋ ๋งค์นญ
text = "Python is amazing"
start_match = re.search(r"^Python", text)  # ๋ฌธ์ž์—ด ์‹œ์ž‘์ด "Python"์ธ์ง€ ํ™•์ธ
print(start_match.group() if start_match else "No match")  # Python

end_match = re.search(r"amazing$", text)  # ๋ฌธ์ž์—ด ๋์ด "amazing"์ธ์ง€ ํ™•์ธ
print(end_match.group() if end_match else "No match")  # amazing

# ๋Œ€์†Œ๋ฌธ์ž ๊ตฌ๋ถ„ ์—†๋Š” ๋งค์นญ
case_insensitive = re.search(r"python", text, re.IGNORECASE)
print(case_insensitive.group() if case_insensitive else "No match")  # Python

# ๋ณต์ˆ˜ ์˜ต์…˜ ์ ์šฉ
multiline_text = """First line
Second line
Third line"""
multiline_match = re.findall(r"^.*line", multiline_text, re.MULTILINE)
print(multiline_match)  # ['First line', 'Second line', 'Third line']

โœ… ํŠน์ง•:

  • ๊ธฐ๋ณธ ๋ฌธ์ž์—ด ๋งค์นญ ๋ฐ ํŒจํ„ด ๊ฒ€์ƒ‰
  • ๋‹ค์–‘ํ•œ ๋ฉ”ํƒ€๋ฌธ์ž๋ฅผ ์ด์šฉํ•œ ํŒจํ„ด ์ •์˜
  • ๋ฌธ์ž์—ด ์œ„์น˜ ๊ธฐ๋ฐ˜ ๋งค์นญ (์‹œ์ž‘, ๋)
  • ์ •๊ทœํ‘œํ˜„์‹ ํ”Œ๋ž˜๊ทธ ํ™œ์šฉ (๋Œ€์†Œ๋ฌธ์ž ๋ฌด์‹œ, ๋ฉ€ํ‹ฐ๋ผ์ธ ๋“ฑ)
  • ๋งค์นญ ๊ฒฐ๊ณผ ์ถ”์ถœ ๋ฐ ์ฒ˜๋ฆฌ
  • ๋‹ค์–‘ํ•œ ์ƒํ™ฉ์— ๋งž๋Š” ํŒจํ„ด ์ ์šฉ
  • ๋‹ค์–‘ํ•œ ์–ธ์–ด์—์„œ ๊ณตํ†ต์ ์œผ๋กœ ์‚ฌ์šฉ๋˜๋Š” ํ‘œ์ค€
  • ํ…์ŠคํŠธ ์ฒ˜๋ฆฌ์˜ ๊ฐ•๋ ฅํ•œ ๋„๊ตฌ


2๏ธโƒฃ ์ž์ฃผ ์‚ฌ์šฉ๋˜๋Š” ํŒจํ„ด

์ •๊ทœํ‘œํ˜„์‹์—์„œ ๊ฐ€์žฅ ํ”ํ•˜๊ฒŒ ์‚ฌ์šฉ๋˜๋Š” ๋ฉ”ํƒ€๋ฌธ์ž์™€ ํŒจํ„ด๋“ค์ด๋‹ค.

import re

# ๊ธฐ๋ณธ ๋ฉ”ํƒ€๋ฌธ์ž
# \d: ์ˆซ์ž [0-9]
# \D: ์ˆซ์ž๊ฐ€ ์•„๋‹Œ ๋ฌธ์ž [^0-9]
# \w: ๋‹จ์–ด ๋ฌธ์ž (์•ŒํŒŒ๋ฒณ, ์ˆซ์ž, ์–ธ๋”์Šค์ฝ”์–ด) [a-zA-Z0-9_]
# \W: ๋‹จ์–ด ๋ฌธ์ž๊ฐ€ ์•„๋‹Œ ๊ฒƒ [^a-zA-Z0-9_]
# \s: ๊ณต๋ฐฑ ๋ฌธ์ž (์ŠคํŽ˜์ด์Šค, ํƒญ, ์ค„๋ฐ”๊ฟˆ ๋“ฑ)
# \S: ๊ณต๋ฐฑ์ด ์•„๋‹Œ ๋ฌธ์ž
# .: ์ž„์˜์˜ ํ•œ ๋ฌธ์ž (์ค„๋ฐ”๊ฟˆ ์ œ์™ธ)

text = "abc123 def456 ghi789"

# ๋ชจ๋“  ์ˆซ์ž ์ฐพ๊ธฐ
numbers = re.findall(r"\d+", text)
print(numbers)  # ['123', '456', '789']

# ๋ชจ๋“  ๋ฌธ์ž ๊ทธ๋ฃน ์ฐพ๊ธฐ
words = re.findall(r"\w+", text)
print(words)  # ['abc123', 'def456', 'ghi789']

# ๋ฌธ์ž์™€ ์ˆซ์ž ๋ถ„๋ฆฌํ•˜๊ธฐ
alphanumeric = re.findall(r"([a-z]+)(\d+)", text)
print(alphanumeric)  # [('abc', '123'), ('def', '456'), ('ghi', '789')]

# ๋ฌธ์ž ํด๋ž˜์Šค
# [...]: ๊ด„ํ˜ธ ์•ˆ์˜ ์–ด๋–ค ๋ฌธ์ž๋“  ๋งค์นญ
# [^...]: ๊ด„ํ˜ธ ์•ˆ์˜ ๋ฌธ์ž๋“ค์„ ์ œ์™ธํ•œ ๋งค์นญ
# [a-z]: ์•ŒํŒŒ๋ฒณ ์†Œ๋ฌธ์ž ๋ฒ”์œ„
# [A-Z]: ์•ŒํŒŒ๋ฒณ ๋Œ€๋ฌธ์ž ๋ฒ”์œ„
# [0-9]: ์ˆซ์ž ๋ฒ”์œ„
# [๊ฐ€-ํžฃ]: ํ•œ๊ธ€ ๋ฒ”์œ„

# ๋ชจ์Œ๋งŒ ์ฐพ๊ธฐ
vowels = re.findall(r"[aeiou]", "Hello World")
print(vowels)  # ['e', 'o', 'o']

# ์ˆซ์ž์™€ ํŠน์ˆ˜๋ฌธ์ž๋งŒ ์ฐพ๊ธฐ
symbols = re.findall(r"[0-9!@#$%^&*]", "password123!")
print(symbols)  # ['1', '2', '3', '!']

# ํ•œ๊ธ€ ์ฐพ๊ธฐ
korean = re.findall(r"[๊ฐ€-ํžฃ]+", "Hello ์•ˆ๋…•ํ•˜์„ธ์š” World")
print(korean)  # ['์•ˆ๋…•ํ•˜์„ธ์š”']

# ์•ต์ปค
# ^: ๋ฌธ์ž์—ด์˜ ์‹œ์ž‘
# $: ๋ฌธ์ž์—ด์˜ ๋
# \b: ๋‹จ์–ด ๊ฒฝ๊ณ„
# \B: ๋‹จ์–ด ๊ฒฝ๊ณ„๊ฐ€ ์•„๋‹Œ ์œ„์น˜

# ๋‹จ์–ด ๊ฒฝ๊ณ„ ํ™œ์šฉ
word_boundary = re.findall(r"\bcat\b", "The cat sat on the cats")
print(word_boundary)  # ['cat']

# ์ด๋ฉ”์ผ ์ฃผ์†Œ ๊ฒ€์ฆ
def is_valid_email(email):
    pattern = r"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$"
    return bool(re.match(pattern, email))

print(is_valid_email("[email protected]"))    # True
print(is_valid_email("invalid_email"))       # False
print(is_valid_email("user@domain"))         # False

# URL ์ถ”์ถœ
text_with_urls = "Visit our website at https://www.example.com or http://subdomain.example.org"
urls = re.findall(r"https?://[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}(?:/\S*)?", text_with_urls)
print(urls)  # ['https://www.example.com', 'http://subdomain.example.org']

โœ… ํŠน์ง•:

  • ๋‹ค์–‘ํ•œ ๋ฌธ์ž ํด๋ž˜์Šค๋ฅผ ํ™œ์šฉํ•œ ํŒจํ„ด ์ •์˜
  • ํŠน์ • ๋ฌธ์ž ์ง‘ํ•ฉ์ด๋‚˜ ๋ฒ”์œ„๋ฅผ ์ง€์ •ํ•˜๋Š” ๋ฐฉ๋ฒ•
  • ๋ถ€์ • ํŒจํ„ด์„ ์‚ฌ์šฉํ•œ ์ œ์™ธ ๋งค์นญ
  • ๋‹จ์–ด ๊ฒฝ๊ณ„์™€ ์œ„์น˜ ์•ต์ปค๋ฅผ ํ™œ์šฉํ•œ ์ •ํ™•ํ•œ ๋งค์นญ
  • ์‹ค์šฉ์ ์ธ ์ •๊ทœํ‘œํ˜„์‹ ํŒจํ„ด ์˜ˆ์ œ (์ด๋ฉ”์ผ, URL ๋“ฑ)
  • ๋ณตํ•ฉ์ ์ธ ํŒจํ„ด ๊ตฌ์„ฑ ๋ฐฉ๋ฒ•
  • ํŒจํ„ด์˜ ๊ฐ€๋…์„ฑ๊ณผ ์œ ์ง€๋ณด์ˆ˜์„ฑ ๊ณ ๋ ค
  • ๋‹ค๊ตญ์–ด ํ…์ŠคํŠธ ์ฒ˜๋ฆฌ ๋ฐฉ๋ฒ•


3๏ธโƒฃ ๋ฐ˜๋ณต ํŒจํ„ด

์ •๊ทœํ‘œํ˜„์‹์—์„œ ๋ฌธ์ž๋‚˜ ํŒจํ„ด์˜ ๋ฐ˜๋ณต์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค.

import re

# ์ฃผ์š” ๋ฐ˜๋ณต ์ˆ˜๋Ÿ‰์ž
# *: 0ํšŒ ์ด์ƒ ๋ฐ˜๋ณต (0๊ฐœ ์ด์ƒ)
# +: 1ํšŒ ์ด์ƒ ๋ฐ˜๋ณต (1๊ฐœ ์ด์ƒ)
# ?: 0ํšŒ ๋˜๋Š” 1ํšŒ ๋ฐ˜๋ณต (์„ ํƒ์ )
# {n}: ์ •ํ™•ํžˆ nํšŒ ๋ฐ˜๋ณต
# {n,}: nํšŒ ์ด์ƒ ๋ฐ˜๋ณต
# {n,m}: nํšŒ ์ด์ƒ mํšŒ ์ดํ•˜ ๋ฐ˜๋ณต

text = "hello 123 world 456"

# * ์ˆ˜๋Ÿ‰์ž: 0ํšŒ ์ด์ƒ
print(re.findall(r"he*llo", "hllo hello heello"))  # ['hllo', 'hello', 'heello']

# + ์ˆ˜๋Ÿ‰์ž: 1ํšŒ ์ด์ƒ
print(re.findall(r"he+llo", "hllo hello heello"))  # ['hello', 'heello']

# ? ์ˆ˜๋Ÿ‰์ž: 0ํšŒ ๋˜๋Š” 1ํšŒ
print(re.findall(r"colou?r", "color colour"))  # ['color', 'colour']

# {n} ์ •ํ™•ํ•œ ๋ฐ˜๋ณต ํšŸ์ˆ˜
pattern = r"ca{2}t"
print(re.findall(pattern, "cat caat caaat"))  # ['caat']

# {n,} ์ตœ์†Œ ๋ฐ˜๋ณต ํšŸ์ˆ˜
pattern = r"ca{2,}t"
print(re.findall(pattern, "cat caat caaat caaaat"))  # ['caat', 'caaat', 'caaaat']

# {n,m} ๋ฐ˜๋ณต ๋ฒ”์œ„
pattern = r"ca{2,3}t"
print(re.findall(pattern, "cat caat caaat caaaat"))  # ['caat', 'caaat']

# ํƒ์š•์  vs ๋น„ํƒ์š•์  ๋ฐ˜๋ณต
greedy_pattern = r"<.+>"
non_greedy_pattern = r"<.+?>"
html = "<p>์ฒซ ๋ฒˆ์งธ ๋‹จ๋ฝ</p><p>๋‘ ๋ฒˆ์งธ ๋‹จ๋ฝ</p>"

# ํƒ์š•์  ๋งค์นญ (๊ธฐ๋ณธ): ๊ฐ€๋Šฅํ•œ ๋งŽ์ด ๋งค์นญ
print(re.findall(greedy_pattern, html))  # ['<p>์ฒซ ๋ฒˆ์งธ ๋‹จ๋ฝ</p><p>๋‘ ๋ฒˆ์งธ ๋‹จ๋ฝ</p>']

# ๋น„ํƒ์š•์  ๋งค์นญ (?): ๊ฐ€๋Šฅํ•œ ์ ๊ฒŒ ๋งค์นญ
print(re.findall(non_greedy_pattern, html))  # ['<p>', '</p>', '<p>', '</p>']

# ๋ณต์žกํ•œ ๋ฐ˜๋ณต ํŒจํ„ด
# ์ „ํ™”๋ฒˆํ˜ธ ํ˜•์‹ ๊ฒ€์ฆ (์˜ˆ: 010-1234-5678 ๋˜๋Š” 010-123-4567)
phone_pattern = r"01[016789]-\d{3,4}-\d{4}"
phones = [
    "010-1234-5678",
    "011-123-4567",
    "016-123-4567",
    "010-12-345",  # ์ž˜๋ชป๋œ ํ˜•์‹
    "010-12345-6789"  # ์ž˜๋ชป๋œ ํ˜•์‹
]

for phone in phones:
    is_valid = re.match(phone_pattern, phone)
    print(f"{phone}: {'์œ ํšจ' if is_valid else '์œ ํšจํ•˜์ง€ ์•Š์Œ'}")

# ๋ฐ˜๋ณต ํŒจํ„ด์„ ํ™œ์šฉํ•œ ๋‹จ์–ด ์ถ”์ถœ
sentence = "Python programming is fun and challenging. Python is powerful."
# Python ๋‹จ์–ด๋งŒ ์ถ”์ถœ
print(re.findall(r"\bPython\b", sentence))  # ['Python', 'Python']

# ๋ฐ˜๋ณต ํŒจํ„ด์— ๊ทธ๋ฃน ๊ฒฐํ•ฉ
date_text = "Date: 2023-05-15, Modified: 2023-06-30"
dates = re.findall(r"(\d{4})-(\d{2})-(\d{2})", date_text)
print(dates)  # [('2023', '05', '15'), ('2023', '06', '30')]

# ์—ฐ์†๋œ ์ˆซ์ž ๋ฐ ๋ฌธ์ž ํŒจํ„ด
text = "123abc456def789ghi"
# ์ˆซ์ž์™€ ๋ฌธ์ž ํŒจํ„ด์ด ๋ฐ˜๋ณต๋˜๋Š” ๊ฒฝ์šฐ
pattern = r"(\d+)([a-z]+)"
matches = re.findall(pattern, text)
print(matches)  # [('123', 'abc'), ('456', 'def'), ('789', 'ghi')]

โœ… ํŠน์ง•:

  • ๋‹ค์–‘ํ•œ ๋ฐ˜๋ณต ์ˆ˜๋Ÿ‰์ž๋ฅผ ์‚ฌ์šฉํ•œ ํŒจํ„ด ๋งค์นญ
  • ์ •ํ™•ํ•œ ๋ฐ˜๋ณต ํšŸ์ˆ˜ ์ง€์ • ๋ฐ ๋ฒ”์œ„ ์„ค์ •
  • ํƒ์š•์ (greedy) ๋ฐ ๋น„ํƒ์š•์ (non-greedy) ๋งค์นญ ๋ฐฉ์‹
  • ๋ณต์žกํ•œ ํŒจํ„ด์—์„œ ๋ฐ˜๋ณต ์ œ์–ด ๋ฐฉ๋ฒ•
  • ์‹ค์ œ ์‘์šฉ ์‚ฌ๋ก€(์ „ํ™”๋ฒˆํ˜ธ, ๋‚ ์งœ ๋“ฑ) ๊ฒ€์ฆ
  • ๋ฐ˜๋ณต ํŒจํ„ด๊ณผ ๊ทธ๋ฃน์˜ ๊ฒฐํ•ฉ
  • ํšจ์œจ์ ์ธ ๋ฐ˜๋ณต ํŒจํ„ด ์ž‘์„ฑ๋ฒ•
  • ๋‹ค์–‘ํ•œ ํ˜•์‹์˜ ํ…์ŠคํŠธ ํŒจํ„ด ๋งค์นญ


4๏ธโƒฃ ๊ทธ๋ฃน๊ณผ ์ฐธ์กฐ

์ •๊ทœํ‘œํ˜„์‹์—์„œ ํŒจํ„ด์˜ ์ผ๋ถ€๋ฅผ ๊ทธ๋ฃนํ™”ํ•˜๊ณ  ์ฐธ์กฐํ•˜๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค.

import re

# ๊ธฐ๋ณธ ๊ทธ๋ฃนํ™” - ๊ด„ํ˜ธ() ์‚ฌ์šฉ
text = "Smith,John"
pattern = r"(\w+),(\w+)"
match = re.match(pattern, text)

if match:
    # ๊ทธ๋ฃน ์ „์ฒด ๋งค์น˜
    print(match.group(0))  # Smith,John
    
    # ๊ฐœ๋ณ„ ๊ทธ๋ฃน ์ ‘๊ทผ
    print(match.group(1))  # Smith
    print(match.group(2))  # John
    
    # ๋ชจ๋“  ๊ทธ๋ฃน ํ•œ ๋ฒˆ์— ๊ฐ€์ ธ์˜ค๊ธฐ
    print(match.groups())  # ('Smith', 'John')

# ์ด๋ฆ„ ์žˆ๋Š” ๊ทธ๋ฃน (?P<name>pattern)
pattern = r"(?P<last>\w+),(?P<first>\w+)"
match = re.match(pattern, text)

if match:
    # ์ด๋ฆ„์œผ๋กœ ๊ทธ๋ฃน ์ ‘๊ทผ
    print(match.group('last'))   # Smith
    print(match.group('first'))  # John
    
    # groupdict() ๋ฉ”์„œ๋“œ๋กœ ์‚ฌ์ „ ํ˜•ํƒœ๋กœ ๊ฐ€์ ธ์˜ค๊ธฐ
    print(match.groupdict())  # {'last': 'Smith', 'first': 'John'}

# ๊ทธ๋ฃน ๋‚ด ์„ ํƒ ํŒจํ„ด (|)
colors = "red green blue yellow"
# red ๋˜๋Š” green ๋˜๋Š” blue ๋งค์นญ
color_pattern = r"(red|green|blue)"
color_matches = re.findall(color_pattern, colors)
print(color_matches)  # ['red', 'green', 'blue']

# ๋น„์บก์ฒ˜ ๊ทธ๋ฃน (?:pattern)
# ๋งค์นญ์€ ํ•˜์ง€๋งŒ ๊ฒฐ๊ณผ์— ํฌํ•จํ•˜์ง€ ์•Š์Œ
text = "apple and banana"
pattern = r"(?:apple|banana) and (\w+)"
match = re.search(pattern, text)
print(match.groups())  # ('banana',)

# ํ›„๋ฐฉ ์ฐธ์กฐ (๋ฐฑ๋ ˆํผ๋Ÿฐ์Šค)
# \๋ฒˆํ˜ธ ๋˜๋Š” \g<๋ฒˆํ˜ธ>๋กœ ์ด์ „ ๊ทธ๋ฃน ์ฐธ์กฐ
html = "<div>๋‚ด์šฉ1</div><span>๋‚ด์šฉ2</span>"

# ์ผ๋ฐ˜์ ์ธ ๋ฐฉ๋ฒ•: ํƒœ๊ทธ ์ด๋ฆ„์ด ์ผ์น˜ํ•˜์ง€ ์•Š์•„๋„ ๋งค์นญ๋จ
print(re.findall(r"<(\w+)>(.*?)</(\w+)>", html))
# [('div', '๋‚ด์šฉ1', 'div'), ('span', '๋‚ด์šฉ2', 'span')]

# ํ›„๋ฐฉ ์ฐธ์กฐ: ์—ฌ๋Š” ํƒœ๊ทธ์™€ ๋‹ซ๋Š” ํƒœ๊ทธ๊ฐ€ ์ผ์น˜ํ•ด์•ผ ํ•จ
print(re.findall(r"<(\w+)>(.*?)</\1>", html))
# [('div', '๋‚ด์šฉ1'), ('span', '๋‚ด์šฉ2')]

# ์ด๋ฆ„ ์žˆ๋Š” ๊ทธ๋ฃน ์ฐธ์กฐ (?P=name)
pattern = r"<(?P<tag>\w+)>(.*?)</(?P=tag)>"
matches = re.findall(pattern, html)
print(matches)  # [('div', '๋‚ด์šฉ1'), ('span', '๋‚ด์šฉ2')]

# ๋ฌธ์ž์—ด ์น˜ํ™˜์—์„œ ๊ทธ๋ฃน ์ฐธ์กฐ
text = "John Smith"
# ์ด๋ฆ„ ํ˜•์‹ ๋ฐ”๊พธ๊ธฐ (First Last -> Last, First)
new_text = re.sub(r"(\w+) (\w+)", r"\2, \1", text)
print(new_text)  # Smith, John

# ์ค‘์ฒฉ ๊ทธ๋ฃน
address = "123 Main St, Anytown, CA 12345"
pattern = r"((\d+) ([A-Za-z\s]+), ([A-Za-z]+), ([A-Z]{2}) (\d{5}))"
match = re.search(pattern, address)

if match:
    # ์ „์ฒด ์ฃผ์†Œ
    print(match.group(1))  # 123 Main St, Anytown, CA 12345
    # ๋ฒˆ์ง€์ˆ˜
    print(match.group(2))  # 123
    # ๋„๋กœ๋ช…
    print(match.group(3))  # Main St
    # ๋„์‹œ
    print(match.group(4))  # Anytown
    # ์ฃผ
    print(match.group(5))  # CA
    # ์šฐํŽธ๋ฒˆํ˜ธ
    print(match.group(6))  # 12345

# lookahead์™€ lookbehind ์–ด์„ค์…˜
# ๊ธ์ •ํ˜• lookahead (?=pattern): pattern์ด ๋’ค์— ์žˆ์–ด์•ผ ๋งค์นญ
# ๋ถ€์ •ํ˜• lookahead (?!pattern): pattern์ด ๋’ค์— ์—†์–ด์•ผ ๋งค์นญ
# ๊ธ์ •ํ˜• lookbehind (?<=pattern): pattern์ด ์•ž์— ์žˆ์–ด์•ผ ๋งค์นญ
# ๋ถ€์ •ํ˜• lookbehind (?<!pattern): pattern์ด ์•ž์— ์—†์–ด์•ผ ๋งค์นญ

# ๋น„๋ฐ€๋ฒˆํ˜ธ ๊ฒ€์ฆ (์˜๋ฌธ, ์ˆซ์ž, ํŠน์ˆ˜๋ฌธ์ž ์กฐํ•ฉ 8์ž ์ด์ƒ)
passwords = ["abc123", "Password1", "P@ssw0rd", "Simple"]

for pwd in passwords:
    # ๊ธ์ •ํ˜• lookahead ์‚ฌ์šฉ
    has_length = re.search(r".{8,}", pwd) is not None
    has_upper = re.search(r"(?=.*[A-Z])", pwd) is not None
    has_digit = re.search(r"(?=.*\d)", pwd) is not None
    has_special = re.search(r"(?=.*[!@#$%^&*])", pwd) is not None
    
    is_valid = has_length and has_upper and has_digit and has_special
    print(f"{pwd}: {'์œ ํšจ' if is_valid else '์œ ํšจํ•˜์ง€ ์•Š์Œ'}")
    # ๊ฒฐ๊ณผ: 'P@ssw0rd'๋งŒ ์œ ํšจ

# ๊ธ์ •ํ˜• lookbehind: $ ๋’ค์˜ ์ˆซ์ž ์ถ”์ถœ
price_text = "Items: $10, $20, $30"
prices = re.findall(r"(?<=\$)\d+", price_text)
print(prices)  # ['10', '20', '30']

# ๋ถ€์ •ํ˜• lookahead: ํŠน์ • ํŒจํ„ด์œผ๋กœ ๋๋‚˜์ง€ ์•Š๋Š” ๋‹จ์–ด
text = "apple, applet, application, apply"
not_ending_with_y = re.findall(r"\b\w+(?!y\b)", text)
print(not_ending_with_y)  # ['apple', 'applet', 'application', 'appl']

โœ… ํŠน์ง•:

  • ๊ด„ํ˜ธ๋ฅผ ์‚ฌ์šฉํ•œ ํŒจํ„ด ์ผ๋ถ€ ๊ทธ๋ฃนํ™”
  • ์ธ๋ฑ์Šค ๋˜๋Š” ์ด๋ฆ„์œผ๋กœ ๊ทธ๋ฃน ์ ‘๊ทผ
  • ๋น„์บก์ฒ˜ ๊ทธ๋ฃน์œผ๋กœ ๋งค์นญ์€ ํ•˜๋˜ ๊ฒฐ๊ณผ์—์„œ ์ œ์™ธ
  • ํ›„๋ฐฉ ์ฐธ์กฐ๋กœ ๋™์ผ ํŒจํ„ด ์žฌ์‚ฌ์šฉ
  • ์ค‘์ฒฉ ๊ทธ๋ฃน์œผ๋กœ ๋ณต์žกํ•œ ํŒจํ„ด ๊ตฌ์กฐํ™”
  • ์ •๊ทœ์‹ ์น˜ํ™˜์—์„œ ๊ทธ๋ฃน ์ฐธ์กฐ ํ™œ์šฉ
  • lookahead์™€ lookbehind ์–ด์„ค์…˜์œผ๋กœ ์กฐ๊ฑด๋ถ€ ๋งค์นญ
  • ๋ณต์žกํ•œ ํ…์ŠคํŠธ ๊ฒ€์ฆ ๋ฐ ์ถ”์ถœ ํŒจํ„ด ๊ตฌํ˜„


โš ๏ธ **GitHub.com Fallback** โš ๏ธ