ํŠน์ • ๋ฌธ์ž์—ด์ด ๋ฐ˜๋ณต๋˜๋Š”์ง€์— ๋Œ€ํ•ด์„œ ์•Œ๊ธฐ ์œ„ํ•ด์„œ๋Š” ์–ด๋– ํ•œ ์ •๊ทœ์‹์„ ์ž‘์„ฑํ•ด์•ผ ํ• ๊นŒ? ์šฐ๋ฆฌ๊ฐ€ ์•ž์—์„œ ๋ฐฐ์šด ๋‚ด์šฉ์œผ๋กœ๋Š” ํ•  ์ˆ˜ ์—†๋‹ค. ์ด๋ ‡๊ฒŒ ํŠน์ • ๋ฌธ์ž์—ด์ด ๋‹จ์œ„๋กœ ๊ตฌ์„ฑ๋˜์–ด ๊ฒ€์ƒ‰์„ ์ง„ํ–‰ํ•˜๊ณ  ์‹ถ์„ ๋•Œ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๊ทธ๋ฃจํ•‘์ด๋‹ค.

(ABC)+
>>> p = re.compile('(ABC)+')
>>> m = p.search('ABCABCABC OK?')
>>> print(m)
<re.Match object; span=(0, 9), match='ABCABCABC'>
>>> print(m.group())
ABCABCABC

()์„ ์‚ฌ์šฉํ•˜์—ฌ ๊ฐ„๋‹จํ•˜๊ฒŒ ๊ทธ๋ฃจํ•‘์„ ์ง„ํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค.

์˜๋ฏธ๋ก ์ ์œผ๋กœ ๊ทธ๋ฃจํ•‘ํ•˜๊ธฐ

์ด๋ ‡๊ฒŒ ๋ฌถ์–ด์„œ ๋ฌด์–ธ๊ฐ€๋ฅผ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค๋ฉด ์ถ”๊ฐ€์ ์œผ๋กœ ์ด์ ์ด ์ƒ๊ธด๋‹ค.

>>> p = re.compile(r"\w+\s+\d+[-]\d+[-]\d+")
>>> m = p.search("park 010-1234-1234")

์ด๋ ‡๊ฒŒ ์ž‘์„ฑํ•˜๊ฒŒ ๋˜๋ฉด, ์ด๋ฆ„ + " " + ์ „ํ™”๋ฒˆํ˜ธ ํ˜•ํƒœ์˜ ๋ฌธ์ž์—ด์„ ์ฐพ์„ ์ˆ˜ ์žˆ๋‹ค. ๊ทธ๋Ÿฐ๋ฐ ์—ฌ๊ธฐ์„œ ์ด๋ฆ„๋งŒ ๋ฝ‘์•„๋‚ด๊ณ  ์‹ถ๋‹ค๋ฉด ์–ด๋–ป๊ฒŒ ํ•ด์•ผํ• ๊นŒ? ์‚ฌ์‹ค ์œ„์˜ ๋ฐ˜๋ณต์˜ ๋ชฉ์ ๋ณด๋‹ค ์ด๋Ÿฐ ์˜๋ฏธ๋ก ์ ์œผ๋กœ ๋ฌถ์–ด์„œ ๋ฝ‘์•„๋‚ด๊ณ ์ž ํ•˜๋Š” ๋ชฉ์ ์ธ ๊ฒฝ์šฐ๊ฐ€ ๋” ๋งŽ๋‹ค. ์ด ๋•Œ ๊ทธ๋ฃจํ•‘์„ ์‚ฌ์šฉํ•ด๋ณด์ž.

>>> p = re.compile(r"(\w+)\s+\d+[-]\d+[-]\d+")
>>> m = p.search("park 010-1234-1234")
>>> print(m.group(1))
park

์ด๋ฆ„์— ํ•ด๋‹นํ•˜๋Š” \w+ ๋ถ€๋ถ„์„ ๊ทธ๋ฃน (\w+)์œผ๋กœ ๋งŒ๋“ค๋ฉด match ๊ฐ์ฒด์˜ group(์ธ๋ฑ์Šค) ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ทธ๋ฃจํ•‘๋œ ๋ถ€๋ถ„์˜ ๋ฌธ์ž์—ด๋งŒ ๋ฝ‘์•„๋‚ผ ์ˆ˜ ์žˆ๋‹ค. group ๋ฉ”์„œ๋“œ์˜ ์ธ๋ฑ์Šค๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์˜๋ฏธ๋ฅผ ๊ฐ–๋Š”๋‹ค.

|group(์ธ๋ฑ์Šค)|์„ค๋ช…| |:--------:------|::----| |group(0)|๋งค์น˜๋œ ์ „์ฒด ๋ฌธ์ž์—ด| |group(1)|์ฒซ ๋ฒˆ์งธ ๊ทธ๋ฃน์— ํ•ด๋‹น๋˜๋Š” ๋ฌธ์ž์—ด| |group(2)|๋‘ ๋ฒˆ์งธ ๊ทธ๋ฃน์— ํ•ด๋‹น๋˜๋Š” ๋ฌธ์ž์—ด| |group(n)|n ๋ฒˆ์งธ ๊ทธ๋ฃน์— ํ•ด๋‹น๋˜๋Š” ๋ฌธ์ž์—ด|

>>> p = re.compile(r"(\w+)\s+(\d+[-]\d+[-]\d+)")
>>> m = p.search("park 010-1234-1234")
>>> print(m.group(2))
010-1234-1234

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์ด 2๊ฐœ์˜ ๊ทธ๋ฃน์ด ๋ฐœ์ƒํ•˜๊ณ , ์ „ํ™”๋ฒˆ์— ํ•ด๋‹นํ•˜๋Š” ๋ถ€๋ถ„์— ์ ‘๊ทผํ•˜๊ณ  ์‹ถ์œผ๋ฉด group(2)๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค. ๊ทธ๋Ÿผ ์ „ํ™”๋ฒˆํ˜ธ์—์„œ ํ†ต์‹ ์‚ฌ ๋ฒˆํ˜ธ๋ฅผ ๋ฝ‘์•„๋‚ด๊ณ ์ž ํ•˜๋ฉด ์–ด๋–ป๊ฒŒ ํ• ๊นŒ?

>>> p = re.compile(r"(\w+)\s+((\d+)[-]\d+[-]\d+)")
>>> m = p.search("park 010-1234-1234")
>>> print(m.group(3))
010

์ด ์˜ˆ์ œ์—์„œ ์•Œ ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์€ group์„ ์ค‘์ฒฉํ•˜์—ฌ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๊ฐ€๋Šฅํ•˜๋‹ค๋Š” ๊ฒƒ์ด๋‹ค. ์ด๋Ÿฐ ๊ฒฝ์šฐ ๋ฐ”๊นฅ์ชฝ์—์„œ ์•ˆ์ชฝ์œผ๋กœ ๋“ค์–ด๊ฐˆ ์ˆ˜๋ก group์˜ index๊ฐ€ ์ฆ๊ฐ€ํ•œ๋‹ค. zero-width assertion์ด๊ธฐ ๋•Œ๋ฌธ์— ์ด ๋ชจ๋“  ์ž‘์—…์ด ๊ฐ€๋Šฅํ•˜๋‹ค๋Š” ๊ฒƒ์„ ์—ผ๋‘ํ•ด๋‘์ž.

๊ทธ๋ฃจํ•‘๋œ ๋ฌธ์ž์—ด ์žฌ์ฐธ์กฐํ•˜๊ธฐ

๊ทธ๋ฃน์˜ ๋˜ ํ•˜๋‚˜ ์ข‹์€ ์ ์€ ํ•œ ๋ฒˆ ๊ทธ๋ฃจํ•‘ํ•œ ๋ฌธ์ž์—ด์„ ์žฌ์ฐธ์กฐ(Backreferences)ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์ด๋‹ค.

>>> p = re.compile(r'(\b\w+)\s+\1')
>>> p.search('Paris in the the spring').group()
'the the'

์ •๊ทœ์‹ (\b\w+)\s+\1์€ (๊ทธ๋ฃน) + " " + ๊ทธ๋ฃน๊ณผ ๋™์ผํ•œ ๋‹จ์–ด์™€ ๋งค์น˜๋จ์„ ์˜๋ฏธํ•œ๋‹ค. ์ด๋ ‡๊ฒŒ ์ •๊ทœ์‹์„ ๋งŒ๋“ค๊ฒŒ ๋˜๋ฉด 2๊ฐœ์˜ ๋™์ผํ•œ ๋‹จ์–ด๋ฅผ ์—ฐ์†์ ์œผ๋กœ ์‚ฌ์šฉํ•ด์•ผ๋งŒ ๋งค์น˜๋œ๋‹ค. ์ด๊ฒƒ์„ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•ด์ฃผ๋Š” ๊ฒƒ์ด ๋ฐ”๋กœ ์žฌ์ฐธ์กฐ ๋ฉ”ํƒ€ ๋ฌธ์ž์ธ \1์ด๋‹ค. \1์€ ์ •๊ทœ์‹์˜ ๊ทธ๋ฃน ์ค‘ ์ฒซ ๋ฒˆ์งธ ๊ทธ๋ฃน์„ ๊ฐ€๋ฆฌํ‚จ๋‹ค. ๋‘ ๋ฒˆ์งธ ๊ทธ๋ฃน์„ ์ฐธ์กฐํ•˜๋ ค๋ฉด \2๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค.

๊ทธ๋ฃจํ•‘๋œ ๋ฌธ์ž์—ด์— ์ด๋ฆ„ ๋ถ™์ด๊ธฐ

์ •๊ทœ์‹ ์•ˆ์— ๊ทธ๋ฃน์ด ๋ฌด์ฒ™ ๋งŽ์•„์ง„๋‹ค๊ณ  ์ƒ๊ฐํ•ด ๋ณด์ž. ์˜ˆ๋ฅผ ๋“ค์–ด ์ •๊ทœ์‹ ์•ˆ์— ๊ทธ๋ฃน์ด 10๊ฐœ ์ด์ƒ๋งŒ ๋˜์–ด๋„ ๋งค์šฐ ํ˜ผ๋ž€์Šค๋Ÿฌ์šธ ๊ฒƒ์ด๋‹ค. ๊ฑฐ๊ธฐ์— ๋”ํ•ด ์ •๊ทœ์‹์ด ์ˆ˜์ •๋˜๋ฉด์„œ ๊ทธ๋ฃน์ด ์ถ”๊ฐ€, ์‚ญ์ œ๋˜๋ฉด ๊ทธ ๊ทธ๋ฃน์„ ์ธ๋ฑ์Šค๋กœ ์ฐธ์กฐํ•œ ํ”„๋กœ๊ทธ๋žจ๋„ ๋ชจ๋‘ ๋ณ€๊ฒฝํ•ด ์ฃผ์–ด์•ผ ํ•˜๋Š” ์œ„ํ—˜๋„ ๊ฐ–๊ฒŒ ๋œ๋‹ค. ๋งŒ์•ฝ ๊ทธ๋ฃน์„ ์ธ๋ฑ์Šค๊ฐ€ ์•„๋‹Œ ์ด๋ฆ„(Named Groups)์œผ๋กœ ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ๋‹ค๋ฉด ์–ด๋–จ๊นŒ? ์ฆ‰ ๋”•์…”๋„ˆ๋ฆฌ์™€ ๊ฐ™์€ ํ˜•์‹์ด๋‹ค. ๊ทธ๋ ‡๋‹ค๋ฉด ์ด๋Ÿฐ ๋ฌธ์ œ์—์„œ ํ•ด๋ฐฉ๋˜์ง€ ์•Š์„๊นŒ?

์ด๋Ÿฌํ•œ ์ด์œ ๋กœ ์ •๊ทœ์‹์€ ๊ทธ๋ฃน์„ ๋งŒ๋“ค ๋•Œ ๊ทธ๋ฃน ์ด๋ฆ„์„ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ–ˆ๋‹ค. ๊ทธ ๋ฐฉ๋ฒ•์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

(?P<name>\w+)\s+((\d+)[-]\d+[-]\d+)

์œ„ ์ •๊ทœ์‹์€ ์•ž์—์„œ ๋ณธ ์ด๋ฆ„๊ณผ ์ „ํ™”๋ฒˆํ˜ธ๋ฅผ ์ถ”์ถœํ•˜๋Š” ์ •๊ทœ์‹์ด๋‹ค. ๊ธฐ์กด๊ณผ ๋‹ฌ๋ผ์ง„ ๋ถ€๋ถ„์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

(\w+) --> (?P<name>\w+)

๋Œ€๋‹จํžˆ ๋ณต์žกํ•ด์ง„ ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์ด์ง€๋งŒ (\w+)๋ผ๋Š” ๊ทธ๋ฃน์— name์ด๋ผ๋Š” ์ด๋ฆ„์„ ๋ถ™์ธ ๊ฒƒ์— ๋ถˆ๊ณผํ•˜๋‹ค. ์—ฌ๊ธฐ์—์„œ ์‚ฌ์šฉํ•œ (?...) ํ‘œํ˜„์‹์€ ์ •๊ทœ ํ‘œํ˜„์‹์˜ ํ™•์žฅ ๊ตฌ๋ฌธ์ด๋‹ค. ์ด ํ™•์žฅ ๊ตฌ๋ฌธ์„ ์‚ฌ์šฉํ•˜๊ธฐ ์‹œ์ž‘ํ•˜๋ฉด ๊ฐ€๋…์„ฑ์ด ์ƒ๋‹นํžˆ ๋–จ์–ด์ง€๊ธด ํ•˜์ง€๋งŒ ๋ฐ˜๋ฉด์— ๊ฐ•๋ ฅํ•จ์„ ๊ฐ–๊ฒŒ ๋œ๋‹ค. ๊ทธ๋ฃน์— ์ด๋ฆ„์„ ์ง€์–ด ์ฃผ๋ ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํ™•์žฅ ๊ตฌ๋ฌธ์„ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค.

(?P<๊ทธ๋ฃน๋ช…>...)

๊ทธ๋ฃน์— ์ด๋ฆ„์„ ์ง€์ •ํ•˜๊ณ  ์ฐธ์กฐํ•˜๋Š” ๋‹ค์Œ ์˜ˆ๋ฅผ ๋ณด์ž.

>>> p = re.compile(r"(?P<name>\w+)\s+((\d+)[-]\d+[-]\d+)")
>>> m = p.search("park 010-1234-1234")
>>> print(m.group("name"))
park

์œ„ ์˜ˆ์—์„œ ๋ณผ ์ˆ˜ ์žˆ๋“ฏ์ด name์ด๋ผ๋Š” ๊ทธ๋ฃน ์ด๋ฆ„์œผ๋กœ ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ๋‹ค. ๊ทธ๋ฃน ์ด๋ฆ„์„ ์‚ฌ์šฉํ•˜๋ฉด ์ •๊ทœ์‹ ์•ˆ์—์„œ ์žฌ์ฐธ์กฐํ•˜๋Š” ๊ฒƒ๋„ ๊ฐ€๋Šฅํ•˜๋‹ค.

>>> p = re.compile(r'(?P<word>\b\w+)\s+(?P=word)')
>>> p.search('Paris in the the spring').group()
'the the'

์œ„ ์˜ˆ์—์„œ ๋ณผ ์ˆ˜ ์žˆ๋“ฏ์ด ์žฌ์ฐธ์กฐํ•  ๋•Œ์—๋Š” (?P=๊ทธ๋ฃน์ด๋ฆ„)์ด๋ผ๋Š” ํ™•์žฅ ๊ตฌ๋ฌธ์„ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค.

Reference