반응형

PHP는 다양한 값을 조작하기 위한 함수가 준비되어 있다. 그 중에 가장 많이 사용되는 '텍스트'와 '시간'에 관한 내용 정리하여 설명하겠다.

텍스트를 다루는 주요 함수

프로그램을 만들 때, 의외로 중요한 것이 "다양한 값을 조작하는 방법"이다. 이것이 알 수 없으면 이런 저런 고민이 많아 진다. 우선은 텍스트를 조작하는 주요 기능에서 소개해 보겠다.

텍스트의 길이를 얻는다.

$변수 = strlen(텍스트);
$변수 = mb_strlen(텍스트);

텍스트가 몇 문자인지 알아낸다. strlen은 일반적인 영어 텍스트(영숫자) 문자를 mb_strlen는 한국어 등 1바이트 문자가 아닌 것에 대해 문자를 확인하여 정수 값으로 반환한다.

$n = strlen('hello'); // $n는 5가 된다.

텍스트의 위치를 조회한다.

$변수 = strpos(대상 텍스트, 검색 문자, 시작 위치);
$변수 = mb_strpos(대상 텍스트, 검색 문자, 시작 위치, 인코딩);

어느 텍스트 안에 조회하려는 텍스트가 있는 위치를 알아내는 것이다. 이것도 1바이트 문자용 strpos와 그외에 다른 문자용의 mb_strpos의 2종류가 준비되어 있다.

첫번째 인수는 조회하려는 대상의 텍스트를, 두번째는 조회할 텍스트를 각각 지정한다. 이 2개는 필수이다. 세번째는 몇번째 문자부터 조회할지 숫자로 지정한다. 네번째는 텍스트 인코딩을 지정한다.

아무튼, 영숫자 조회(strpos)는 처음에 2개만 호출하면 보통은 될 것이다. 하지만, 한국어 등을 조회할 mb_strpos의 경우 4개 모두를 지정하는 것이 기본 생각해 두자. 특히, 4번째 인코딩을 제대로 지정하지 않으면 잘 찾아지지 않을 수도 있다.

반환값은 몇번째 문자인지 (최초는 0이 된다)을 나타내는 정수이다. 발견되지 않는 경우는 false가 반환된다.

$n = strpos("Hello","e",0,"UTF-8"); // $n는 1이 된다.

텍스트의 일부를 추출한다.

$변수 = substr(텍스트, 시작 위치, 길이);
$변수 = mb_substr(텍스트, 시작 위치, 길이, 인코딩);

텍스트 중에서 지정한 부분의 텍스트를 반환한다. 예를 들어 "Hello PHP World"라는 텍스트 중에서 "PHP"만 추출하려고 할 경우에 사용한다.

첫 번째 인수는 추출하려는 원래 텍스트를 지정하고 두번째, 세 번째 추출하려는 위치와 문자(길이)를 각각 지정한다. 위치는 가장 최초가 0부터 시작된다. 또한 한국어 등의 경우 mb_substr는 반드시 인코딩을 지정하도록 한다.

$s = substr("Hello",2,2); // $s는 "ll"가 된다.

텍스트를 치환한다.

$변수 = str_replace(검색 문자, 대체 문자, 텍스트);

텍스트 치환은 str_replace라는 편리한 함수가 준비되어 있다. 검색 문자와 치환하려는 문자, 그리고 대상이 되는 텍스트를 지정해주는 것만으로 대체된 텍스트가 반환된다. 이것은 한국어용의 함수라는 것은 준비되어 있지 않는다. 모든 이 하나에서 실행한다.

이 함수는 세번째의 텍스트에 포함된 검색 문자를 모두 치환 문자로 대체한 것을 돌려준다.

$s = str_replace("java","PHP","Hello java!"); // $s는 "Hello PHP!"가 된다


정규 표현식

텍스트를 다룰 때, 피할 수 없는 것이 "정규식"라는 것이 있다. 이것은 "패턴"이라는 텍스트의 정렬의 법칙 같은 것을 준비하고 그에 따라 텍스트를 찾아 내거나 대체 할 수 있는 기능이다.

일반 검색 치환은 정해진 텍스트를 찾을 수 밖에 없다. 예를 들어 "PHP"라는 단어를 찾아라는 방식이다. 이에 비해 정규 표현식은 "어떤 법칙에 늘어선 텍스트인가"을 확인할 수 있다. 예를 들어 "3자리 숫자를 검색"이라든지, "a로 시작 s로 끝나는 텍스트 찾기" 같은 것을 할 수 있다.

정규식의 패턴은 "메타 문자(meta character)"라는 특수 기호를 사용하여 조합한다. 여기에는 다양한 기호와 규칙이 준비되어 있다. 아래의 목록에 목록을 올려 두었습니다.

※ 기본 메타 문자

기호설명
\일반적인 회피 문자
^검색대상 (멀티 라인 모드에서는 행)의 처음)
$검색대상 (멀티 라인 모드에서는 행)의 끝
.개행(줄바꿈)을 제외한 모든 문자와 일치
[]문자 클래스
|선택지의 시작
()서브 패턴
?(의미 확장, 0 또는 1 회 반복, 반복을 최소화
*0 이상의 반복
+1 이상의 반복
{}최소 / 최대 반복 지정

※ 문자 클래스에서 사용할 수있는 특수 문자

메타 문자설명
\이스케이프 문자
\b백 스페이스
\f페이지 넘김 (form feed)
\n줄 바꿈 (new line)
\r줄 바꿈 (carriage return)
\t탭(tab) 문자
\d숫자 하나 ([0-9]와 같다)
\s공백 처리 문자 (공백, 줄 바꿈, 줄 바꿈, 탭 문자)
\w숫자 + 알파벳 + 밑줄, 대소문자와 밑줄을 포함하는 모든 영숫자([a-zA-Z0-9_]와 같다
^부정
-범위
  • 이 중 ^ - 이외는 문자 클래스 밖에서도 사용 가능하다.

※ 문자 클래스 외부에서 사용하는 특수 문자

메타 문자설명
\a경보
\c컨트롤 기호 (이 후에 문자를 지정)
\e이스케이프
\D숫자를 제외한 문자 하나 ([^0-9]와 같다)
\S공백 문자가 아닌 모든 문자 ([^\f\n\r\t\v]와 같다)
\W'숫자 + 알파벳 + 밑줄」이외 모든
\b단어의 구분
\B단어 경계 이외
\A텍스트의 시작
\Z텍스트의 종료 또는 개행
\z텍스트의 끝
\ddd8 진수로 ddd 문자
\xhh16 진수 hh 문자

※ 패턴 변경자

메타 문자설명
i패턴 중의 문자는 대문자와 소문자를 매치
m검색 대상 문자열을 단일 행으로 구성된 처리
s.를 줄바꿈을 포함한 모든 문자와 매치
x공백 문자을 무시
epreg_replace()는 PHP 코드로 평가
A선두에서만 매치
D$를 마지막에만 매치
S보다 시간이 걸렸다 분석을 실시
U매치 최단, 최장의 방식을 반대로 한다
XPerl비 호환 기능의 이용
u패턴을 UTF-8로 한다
  • 이 문자들은 패턴의 성격을 규정하는 것으로, 패턴에 포함되지 않는다.

이를 "모두 기억해야 한다"라고는 말하지 않았다. 실제로 전부 기억 사용하고 있는 사람은 그리 많지 않을 것이다. 자주 사용할 것 같은 기호를 몇 가지 기억하는 것만으로도 정규식의 대단함은 실감할 수있을 것이다.

이 정규 표현식을 사용하기 위해 함수에는 몇 가지가 준비되어 있다. 우선은 "패턴 매치"와 "대체"에 대한 의미를 기억해두면 좋을 것이다.

패턴 매치용 함수

$변수 = preg_match(패턴, 텍스트, $변수);
$변수 = preg_match_all(패턴, 텍스트, $변수);

첫번째 인수의 패턴을 사용하여, 두번째 텍스트를 조사해, 패턴과 일치하는 (패턴에 부합하는 텍스트가 발견) 건수를 반환한다. preg_match는 처음 패턴 매치만, preg_match_all 모든 패턴 일치를 확인한다.

매우 흥미로운 것은 세번째 인수 준비하는 변수이다. 이것은 어떤 값을 지정하는 것은 아니다. 패턴 일치 한 결과를 이 변수에 얻을 것이다. 이는 다차원 배열의 형태로 되어 있고, 각각의 매치한 텍스트 정보를 모은다.

또한 네번째 인수로 패턴 매치에 대한 섬세한 플래그를 지정할 수도 있다. 이것은 본격적으로 정규 표현식을 사용하게 되었을 알아보도록 한다.

치환용 함수

$변수 = preg_replace(패턴, 대체 문자, 텍스트);

정규식을 사용하여 치환할 함수이다. 첫번째 인수는 패턴, 두번째 인수에는 대체 문자, 그리고 세번째로 조사의 대상이 되는 텍스트를 각각 전달한다. 반환값은 대체된 텍스트가 전달된다.

우선,이 3개를 알면 여러가지를 할 수 있게 될 것이다. 패턴 매치는 텍스트 데이터 중에서 특정 요소를 선택하고 (예를 들어, HTML 소스 코드에서 <a> 태그 링크 및 이메일 주소만 찾아 다닐수 있다), 치환할 수 있다면 절대로 정상적인 치환으로는 할 수 없는 복잡한 치환 처리를 할 수 있게 된다.

정규식 사용 예

그럼 정규식 사용 예제를 작성해 보고 실행을 시켜 보자.

<?php
    if ($_POST != null){
        $url = $_POST['text1'];
        $lines = file($url);
        $data = implode($lines);
        // 패턴 매치
        $pattern = "/([\w-]+)@([\w\.-]+)\b/";
        $flg = preg_match_all($pattern, $data, $matchs);
        if ($flg != false){
            $result = "";
            foreach($matchs[0] as $key => $val){
                $result .= $val . "\n";
            }
        } else {
            $result = "없다.";
        }
    }
?>
<!DOCTYPE html>
<html lang="ko">
    <head> 
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> 
        <title>sample page</title>
    </head>
    <body>
        <h1>Hello PHP!</h1>
        <form method="post" action="./index.php">
            <input type="text" name="text1" size="40" value="<?php echo htmlspecialchars($url); ?>"><br>
            <textarea name="area1" cols="30" rows="5"><?php echo $result; ?></textarea><br>
            <input type="submit">
        </form>
        <hr>
    </body>
</html>

여기에는 URL을 입력하면 해당 페이지의 텍스트를 얻어서 거기에서 이메일 주소만 찾아 표시시켜 보자.

위에 입력 필드에 http://~와 같은 식으로 조사하고 싶은 페이지의 URL을 입력하여 전송을 해보자. 그 페이지에 적혀있는 이메일 주소를 찾아서 아래의 텍스트 영역에 표시될 것이다.

여기에서는 먼저 file 함수를 사용하여 URL의 텍스트를 읽어 들여, 그것을 implode으로 하나의 텍스트로 정리한다. 그리고, 패턴을 사용하여 패턴 매칭을 실행하고 있다.

$pattern = "/([\w-]+)@([\w\.-]+)\b/";

이것이 준비한 패턴이다. 대체로, 여기에서 "헉, 정규식 어렵다. 무리야"라고 포기해 버리는 사람들이 많지만, 솔직히 그럴 필요는 없다. 정규식 패턴으로 인터넷으로 검색해 보면 이메일 주소 라든지, URL 든가, 비교적 자주 사용되는 패턴을 공개주는 사람이 많다. 그러한 패턴을 복사하여 사용하면 우선 패턴을 만들 수없어도 정규 표현식을 사용할 수 있다. 그리고 조금씩 스스로 공부하고 가면 나중에 도움이 될 때가 있을 거다.

$flg = preg_match_all($pattern, $ data, $ matchs);

여기가 패턴 매치를 실행하는 부분이다. 이 자체는 별로 어려운 것은 없다. 실행을 하면 이 $matchs라는 변수에 패턴 일치한 결과가 담긴다.

이 변수는 꽤 복잡한 구조로 되어 있다. 일치하는 텍스트를 얻으려면 인덱스가 0인 값을 꺼낸다. 여기에 연관 배열이 들어 있고, 그 값 부분에 찾아낸 텍스트(즉, 찾아낸 이메일 주소)가 저장되어 있다.

정리하면, 패턴 매치는 "결과의 배열 인덱스가 0인 연관 배열에서 값을 꺼낸다"라는 작업에서 찾아낸 모든 텍스트를 얻을 수 있다. 이것만 염두에 두면, 패턴 매치를 어느정도는 사용할 있을 것이다.

참조

이보다 더 자세한 내용을 알고 싶다면 아래 싸이트를 참고 바란다.



시간에 대한 주요 기능

이어서 일시 설명하겠다. 시간이라는 것은 컴퓨터의 내부와 일반 세계에서 확실히 취급 방법이 다르다. 컴퓨터에서 시간은 "어느 기준이 되는 날짜로부터 경과"에 의해 표현된다.

PHP에서 일시는 "타임 스탬프(timestamp)"라는 값으로 표현된다. 이는 1970년 1월 1일 오전 0시 정각부터 경과된 초 단위로 표시한 것이다. 이 정수의 값은 시간을 나타내는데 가장 기본이 된다.

그러나 그런 수치는 사람이 바로 알 수 없기 때문에, 그것을 바탕으로 하여 "년, 월, 일, 시, 분, 초"의 값으로 일시를 얻을 수 있도록 하는 함수가 준비되어 있다.

현재의 타임 스탬프를 얻기

$변수 = time();

우선 기본으로 타임 스탬프를 얻는 함수이다. 이것으로 지금 현재의 타임 스탬프 값을 얻을 수 있다.

일시의 요소를 배열로 얻기

$변수 = getdate(타임 스탬프);

이 함수는 일시 사용의 기본이 된다. 이것은 인수에 타임 스탬프 값을 넣으면 "년,월,일,시,분 초" 각각의 값을 연관 배열로 반환한다. 인수를 생략하면 현재 시간 값을 돌려준다. 반환되는 연관 배열에 포함되는 주요 요소는 다음과 같다.

  • year : 년
  • mon : 월
  • mday : 일
  • hours : 시
  • minutes : 분
  • seconds : 초
  • wday : 요일 (0 ~ 6의 정수)

일시 값에서 타임 스탬프를 얻기

$변수 = mktime(시, 분, 초, 월, 일, 년);

이번에는 반대이다. "년, 월, 일, 시, 분, 초" 숫자를 바탕으로, 그 시간의 타임 스탬프 값을 검사하는 함수이다. 일단 인수가 6개나 있지만, 실은 필수적인 것은 첫번째 뿐이다. 이후에는 생략하면 현재 날짜와 시간 값이 자동으로 적용시킬 수 있다.

그럼 간단한 사용 예제를 보도록 하자.

<?php
    if ($_POST != null){
        $num = $_POST['text1'] * 1;
        $t = time() + (60 * 60 * 24 * $num);
        $d = getdate($t);
        $result = "오늘 부터 " . $num . "일 후는、" .
            $d['year'] . "년" . $d['mon'] . "월" .
            $d['mday'] . "일 입니다.";
    }
?>
<!DOCTYPE html>
<html lang="ko">
    <head> 
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> 
        <title>sample page</title>
    </head>
    <body>
        <h1>Hello PHP!</h1>
        <p><?php echo $result; ?></p>
        <hr>
        <form method="post" action="./index.php">
            <input type="text" name="text1">
            <input type="submit">
        </form>
        <hr>
    </body>
</html>

위에 예제는 입력 필드에 날짜를 적어 제출하면 오늘부터 그 기간 이후의 날짜를 계산하고 표시를 한다.

우선 time에서 현재의 타임 스탬프를 취득하여, 그에 지정된 날짜의 초(60 × 60 × 24 × 일수)을 더해 지정된 기간 후에 타임 스탬프를 계산하고 마지막으로 getdate에서 타임 스탬프 년월일을 얻으면 끝이다. 중간에 타임 스탬프는 단순한 정수로 변환하여 계산하면 의외로 간단하다.

날짜 계산을 수행

날짜를 사용한 계산을 수행해 보자. 여기에서는 날짜 값을 입력 받아, 오늘부터 그 날까지 며칠인지 알아 보겠다.

우선 예제 코드부터 보도록 하겠다.

<?php
    if ($_POST != null){
        $str = $_POST['text1'];
        $d = explode("/", $str);
        $t1 = time();
        $t2 = mktime(0, 0, 0, $d[1], $d[2], $d[0]);
        $n = ceil(($t2 - $t1) / (60 * 60 * 24));
        $result = $str . "은、오늘부터 {$n} 일 후입니다.";
    }
?>
<!DOCTYPE html>
<html lang="ko">
    <head> 
        <meta http-equiv="Content-Type"
            content="text/html; charset=UTF-8" /> 
        <title>sample page</title>
    </head>
    <body>
        <h1>Hello PHP!</h1>
        <p><?php echo $result; ?></p>
        <hr>
        <form method="post" action="./index.php">
            <input type="text" name="text1">
            <input type="submit">
        </form>
        <hr>
    </body>
</html>

입력 필드에 "2020/1/13"과 같이 년월일을 슬래시(/)로 구분하여 작성하여 전송하면, 오늘부터 그 날까지의 일수를 계산하여 표시한다.

이전에는 오늘부터 며칠 후 날짜를 계산했지만, 여기에서는 계산의 기본은 "타임 스탬프 변경한다"이다. 두 날짜를 각각 타임 스탬프를 변경하여, 그 차이를 계산하여 1일의 초로 나누면 일수 알 수 있다.

$str = $ _POST [ 'text1'];
$d = explode("/", $ str);

먼저 전송된 텍스트를 explode으로 슬래쉬(/) 기호로 분해하여 날짜를 배열로 만든다.

$t1 = time();
$t2 = mktime(0,0,0, $ d [1], $ d [2], $ d [0]);

이어서 현재 날짜와 준비한 배열 값의 날짜 및 시간 스탬프를 각각 준비한다.

$n = ceil(($t2 - $t1) / (60 * 60 * 24));

2개의 타임 스탬프의 차이를 60 × 60 × 24로 나누면 일수가 나온다. 그러나 이번에는 시분초는 지정을 하지 않았기 때문에, 소수점 이하가 표시될 것이다. 그래서 소수점 이하를 잘라내기 위해, "ceil"라는 함수를 사용하고 있다. 이는 소수점 이하를 반올림한 값을 반환하는 함수이다.

이와 같이, 일시 관계는 "년, 월, 일, 시, 분, 초" 값과 타임 스탬프를 교대로 교환할 수있는 방법만 알면 간단한 계산 등은 쉽게 수행할 수 있다.



반응형

'php' 카테고리의 다른 글

[php] 구조와 객체 지향  (0) 2017.12.09
[php] 페이지 전환, 쿠키, 세션  (0) 2017.12.09
[php] 텍스트 및 날짜 조작  (0) 2017.12.09
[php] 텍스트 파일 이용  (0) 2017.12.09
[php] form 전송 기본  (0) 2017.12.09
[php] 제어 구문  (0) 2017.12.09

+ Recent posts