[PHP] 문자열에 특수문자 또는 일부 문자열이 포함되어 있는지 확인 - strpos(), preg_match()
함께 읽어보면 좋은 글
https://weavingcoding.tistory.com/32
[PHP] strpos() 사용시 주의사항! - PHP 버전 7.3 미만인 경우
서론 사용자가 선택한 값에 부분 문자열이 포함되어 있는가 아닌가의 여부로 서버 종류를 판별하고 각자에 맞는 저장 쿼리를 실행하는 코드를 작성하였습니다. // $type = 'user_board' - 사용자 게시
weavingcoding.tistory.com
서론
저희 회사엔 각 시도별로 다양한 이벤트를 진행합니다.
그리고 이 쿠폰들 사용내역을 매주 각 지자체에 보고해야 합니다.
쿠폰이 30개쯤 되니까 일일이 DB조회해주기 번거로워서 자동화를 했습니다.
- 조회하고자 하는 기간 내에 선택한 시도에서 시행되는 쿠폰들의 목록을 만들고
- 같은 종류(①또는②)에 같은 이벤트인, 시군구만 다른 쿠폰끼리 묶어준 다음
- foreach로 쿠폰마다 사용내역을 조회해 엑셀로 export
이렇게 시스템을 짰는데 2번 단계에서 쿠폰들이 그룹화하지 못하는 문제가 발생했습니다.
원인은 쿠폰명에 쿠폰종류를 구분하기위해 들어간 ①과 ② 같은 특수문자 때문이었습니다.
strpos()
구글에서 PHP 같은 문자열
같은 키워드로 검색하면 가장먼저 나오는 예제가
strpos()
에 대한 예제입니다.
사용방법은 다음과 같습니다.
strpos($원본문자열, $비교문자열, $offset)
변수명 | 필수여부 | 설명 |
$원본문자열 | 필수 | 비교할 원본 문자열입니다. $비교문자열을 포함하는지 확인합니다. |
$비교문자열 | 필수 | 비교 기준이 되는 일부 문자열입니다. $원본문자열에 포함되는지 확인합니다. |
$offset | 비교를 시작할 위치를 지정합니다. 만약 음수라면 $원본문자열의 끝에서 n번째부터 비교를 시작합니다. |
하지만 strpos('① [지역명] OO 이벤트 쿠폰', '① [')
을 실행했을 때 false
를 응답받았습니다.
특수문자 ①의 포함여부를 판단하지 못합니다.
preg_match()
이 함수는 정규식을 사용하여 문자열 포함여부를 판단합니다.
그중 /u
를 이용하면 유니코드로 문자열을 변환해 비교할 수 있게 되죠.
유니코드로 비교하면 특수문자로 비교할 수 있게 됩니다!
사용법은 다음과 같습니다.
preg_match($패턴(비교문자열), $원본문자열, $일치결과저장변수, $플래그, $offset)
변수명 | 필수여부 | 설명 |
$패턴(비교문자열) | 필수 | 비교 기준이 되는 일부 문자열을 정규식을 이용해 패턴화 합니다. $원본문자열에 포함되는지 확인합니다. |
$원본문자열 | 필수 | 비교할 원본 문자열입니다. $비교문자열을 포함하는지 확인합니다. |
$일치결과저장변수 | 일치한 결과를 배열로 저장합니다. | |
$플래그 | PREG_OFFSET_CAPTURE 와 PREG_UNMATCHED_AS_NULL 두 가지 플래그가 있습니다. |
|
$offset | 비교를 시작할 위치를 지정합니다. 만약 음수라면 $원본문자열의 끝에서 n번째부터 비교를 시작합니다. |
이제 위에서 실패했던 쿠폰명 비교를 해봅시다!
정규식은... Chat GPT의 도움을 받았습니다. ;ㅅ;
preg_match('/① \[(?=[^\]]*] OO 이벤트 쿠폰)/u', '① [성남] OO 이벤트 쿠폰')
이처럼 정규식을 이용하면 특수문자 뿐만 아니라 양끝 문자열을 동시에 비교할 수 있게 됩니다.
혹시나 해서 strpos()에 동일한 정규식을 넣어도 동작하지 않네요...ㅠ
결론
일반적으로 부분 문자열을 포함하는지 여부를 strpos()로 확인합니다.
하지만 특수문자가 부분 문자열에 포함된 경우 이를 유니코드로 변환해 비교해야하므로,
preg_match()를 써야 합니다.
물론 정규식은 가독성도 낮고
특수문자를 비교할 경우도 적을테지만...
그리고 차라리 특수문자 입력을 막는게 더 나을 수 있지만...!
저처럼 레거시 코드를 최대한 이용해야하는 경우라면
유용한 글이 되셨으면 좋겠습니다. 0ㅅ<