preg_match($pattern, $subject, $matches)는 문자열이 정규 표현식과 일치하는지 확인합니다. 일치하면 1, 아니면 0을 반환하고, 찾은 것으로 $matches를 채웁니다: preg_match('/\d+/', 'Order 4521 shipped', $m)은 1을 반환하고 $m[0]을 "4521"로 설정합니다.
패턴은 구분자(보통 /.../)로 감싼 문자열이며, 그 뒤에 i 같은 수식어가 옵니다. 패턴은 작은따옴표로 쓰세요. 큰따옴표 안에서는 PHP가 먼저 $name과 \x41이나 \101 같은 이스케이프를 확장하므로, 정규식 엔진이 입력한 것과 다른 패턴을 받을 수 있습니다.
캡처 그룹
패턴의 괄호는 그것이 일치하는 문자열 부분을 캡처합니다. $m[0]은 전체 일치, $m[1]은 첫 번째 그룹, $m[2]는 두 번째 그룹이며, 왼쪽부터 여는 괄호 순서로 셉니다.
이름 있는 그룹
(?<name>...)은 그룹에 이름을 붙입니다. 값은 이름과 번호 아래에 모두 저장되므로, 누군가 패턴 앞쪽에 그룹을 추가해도 결과를 읽는 코드가 깨지지 않습니다.
preg_match_all로 모든 일치 찾기
preg_match_all()은 첫 번째 일치 후에도 계속 검색하고 일치 개수를 반환합니다. 기본적으로 $m[0]에는 모든 전체 일치가, $m[1]에는 첫 번째 그룹의 모든 값이 들어갑니다. PREG_SET_ORDER를 쓰면 일치마다 배열 하나를 받으므로 반복하기가 더 쉽습니다.
입력 검증: 앵커, 전화번호, 우편번호
검증에서는 패턴이 문자열 전체와 일치해야 하므로 ^로 시작하고 $로 끝내세요. 함정이 하나 있습니다. $는 마지막 줄바꿈 앞에서도 일치하므로 '/^\d+$/'는 "123\n"을 받아들입니다. D 수식어를 추가하거나, 맨 끝에서만 일치하는 \z를 쓰세요.
이메일 주소에 정규식을 쓰면 유효한 주소를 거부하거나 잘못된 주소를 받아들이게 됩니다. 대신 filter_var($email, FILTER_VALIDATE_EMAIL)를 쓰세요(filter_var() 참고).
UTF-8과 일본어 텍스트를 위한 u 수식어
u 수식어가 없으면 패턴은 바이트 단위로 동작합니다. 일본어 문자(한글도)는 UTF-8에서 3바이트이므로 .이 문자의 3분의 1과 일치하고 길이가 틀리게 나옵니다. u를 쓰면 패턴이 문자 단위로 동작하고 유니코드 속성 클래스를 쓸 수 있습니다.
u는 대상 문자열도 검증합니다. 문자열이 올바른 UTF-8이 아니면 preg_match()는 일치 대신 false를 반환합니다.
preg_quote로 사용자 입력 이스케이프하기
., +, ?, (, / 같은 문자는 패턴에서 특별한 의미를 가집니다. 검색어처럼 패턴의 일부가 변수에서 온다면 구분자를 두 번째 인수로 주어 preg_quote()에 통과시키세요. 그렇지 않으면 1+1이 11과 일치하고, 이스케이프하지 않은 /는 패턴을 깨뜨립니다.
잘못된 패턴은 예외를 던지지 않습니다. PHP가 경고를 출력하고 preg_match()는 false를 반환합니다.
Warning: preg_match(): No ending delimiter '/' found in /path/to/index.php on line 3
그러므로 패턴을 실행 시점에 만든다면 === false(또는 preg_last_error_msg())로 확인하세요. 패턴 없이 단순한 부분 문자열 확인이라면 str_contains()가 더 빠르고 명확합니다. 일치한 텍스트를 바꾸려면 preg_replace()를 쓰세요.
자주 묻는 질문
PHP에서 preg_match는 무엇을 반환하나요?
패턴이 일치하면 1, 일치하지 않으면 0, 패턴 자체가 잘못되었으면 false입니다. 0과 false는 둘 다 거짓으로 취급되므로, 잘못된 패턴과 불일치를 구별해야 할 때는 === 1로 비교하세요.
preg_match에서 일치한 텍스트를 얻으려면 어떻게 하나요?
세 번째 인수를 넘기세요: preg_match('/(\d+)/', 'Order 4521', $m). 그러면 $m[0]은 전체 일치, $m[1]은 첫 번째 캡처 그룹이며, 여기서는 둘 다 "4521"입니다. 이름 있는 그룹 (?<id>\d+)를 쓰면 값이 $m['id']에도 들어갑니다.
preg_match와 preg_match_all의 차이는 무엇인가요?
preg_match()는 첫 번째 일치에서 멈춥니다. preg_match_all()은 모든 일치를 찾고, 찾은 개수를 반환하며, $matches를 그 모두로 채웁니다: preg_match_all('/\d+/', 'a1 b22 c333', $m)은 3을 반환하고 $m[0]은 ["1", "22", "333"]입니다.
한글이나 일본어 등 UTF-8 텍스트에 preg_match를 쓰려면 어떻게 하나요?
u 수식어를 추가하세요: preg_match('/^.{3}$/u', '日本語')는 1을 반환합니다. u가 없으면 PHP는 문자열을 바이트로 취급하므로 .이 3바이트 문자의 1바이트와 일치합니다. u를 쓰면 \p{Han}, \p{Hiragana}, \p{Katakana} 같은 유니코드 클래스도 쓸 수 있습니다.
PHP에서 문자열이 숫자로만 되어 있는지 확인하려면 어떻게 하나요?
preg_match('/^\d+$/D', $s) 또는 정규식 없이 ctype_digit($s)를 쓰세요. D 수식어(또는 $ 대신 \z)가 중요합니다. 그냥 $는 끝의 줄바꿈도 허용하므로 "123\n"이 통과합니다.