PHP에는 두 가지 정규식 함수 라이브러리 세트가 있습니다. 한 세트는 PCRE(Perl Compatible Regular)에서 제공됩니다.
Expression) 라이브러리가 제공됩니다. PCRE 라이브러리는 "preg_" 접두사가 붙은 함수를 사용하여 Perl과 동일한 구문 규칙을 사용하여 정규식 패턴 일치를 구현합니다. 또 다른 세트는 POSIX(Portable
운영 시스템 인터페이스) 확장 라이브러리 제공. POSIX의 POSIX 확장 정규식
1003.2 정의에서는 일반적으로 접두사 "ereg_"로 명명된 함수를 사용합니다.
두 함수 라이브러리의 기능은 비슷하지만 실행 효율성이 약간 다릅니다. 일반적으로 동일한 기능을 달성하려면 PCRE 라이브러리를 사용하는 것이 효율성이 약간 우수합니다. 그 사용법은 아래에 자세히 설명되어 있습니다.
6.3.1 정규식 매칭
1. preg_match()
함수 프로토타입: int preg_match (string $pattern, string $content [, array $matches])
preg_match
() 함수는 $pattern에 지정된 정규식과 일치하는 콘텐츠를 $content 문자열에서 검색합니다. $matches가 제공되면 일치하는 결과가 해당 위치에 배치됩니다.
가운데. $matches[0]에는 전체 패턴과 일치하는 텍스트가 포함되고, $matches[1]에는 괄호로 묶인 패턴 요소의 첫 번째 캡처된 일치 항목이 포함됩니다. 이 기능만
일치를 만들고 결국 일치하는 결과 수 0 또는 1을 반환합니다. Listing 6.1은 preg_match() 함수에 대한 코드 예제를 보여줍니다.
코드 6.1 날짜 및 시간 일치
<?php //需要匹配的字符串。date函数返回当前时间 $content = "Current date and time is ".date("Y-m-d h:i a").", we are learning PHP together."; //使用通常的方法匹配时间 if (preg_match ("/\d{4}-\d{2}-\d{2} \d{2}:\d{2} [ap]m/", $content, $m)) { echo "匹配的时间是:" .$m[0]. "\n"; } //由于时间的模式明显,也可以简单的匹配 if (preg_match ("/([\d-]{10}) ([\d:]{5} [ap]m)/", $content, $m)) { echo "当前日期是:" .$m[1]. "\n"; echo "当前时间是:" .$m[2]. "\n"; } ?>
간단한 동적 텍스트 문자열 일치 예입니다. 현재 시스템 시간이 "2006년 8월 17일 13시 25분"이라고 가정하면 다음과 같은 내용이 출력됩니다.
매칭 시간은 : 2006-08-17
오후 01:25
현재 날짜: 2006-08-17
현재 시간: 오후 01:25
2. ereg() 및 eregi()
ereg()는 POSIX 확장 라이브러리의 정규식에 대한 일치 함수입니다. eregi()는 ereg() 함수의 대소문자를 무시하는 버전입니다.
책. 둘 다 preg_match와 유사한 함수를 가지고 있지만 이 함수는 일치가 성공했는지 여부를 나타내는 부울 값을 반환합니다. POSIX 확장 라이브러리 함수의 첫 번째 매개변수는 일반 매개변수를 허용한다는 점에 유의해야 합니다.
표현식 문자열, 즉 구분 기호가 필요하지 않습니다. 예를 들어, 목록 6.2는 파일 이름의 보안을 확인하는 방법입니다.
코드 6.2 파일 이름 보안 검사
<?php $username = $_SERVER['REMOTE_USER']; $filename = $_GET['file']; //对文件名进行过滤,以保证系统安全 if (!ereg('^[^./][^/]*$', $userfile)) { die('这不是一个非法的文件名!'); } //对用户名进行过滤 if (!ereg('^[^./][^/]*$', $username)) { die('这不是一个无效的用户名'); } //通过安全过滤,拼合文件路径 $thefile = "/home/$username/$filename"; ?>
일반적으로 Perl 호환 정규식 일치 함수 perg_match()를 사용하는 것이 ereg() 또는 eregi()를 사용하는 것보다 빠릅니다. 문자열에 특정 하위 문자열이 포함되어 있는지 확인하려면 strstr() 또는 strpos() 함수를 사용하는 것이 좋습니다.
3. preg_grep()
함수 프로토타입: 배열 preg_grep(문자열 $pattern,
배열 $입력)
preg_grep() 함수는 주어진 $pattern 패턴과 일치하는 $input 배열의 셀을 포함하는 배열을 반환합니다. Preg_grep()은 또한 입력 배열 $input의 각 요소에 대해서만 일치를 수행합니다. Listing 6.3의 예제는 preg_grep() 함수의 사용법을 간단히 보여줍니다.
코드 6.3 배열 쿼리 매칭
<?php $subjects = array( "Mechanical Engineering", "Medicine", "Social Science", "Agriculture", "Commercial Science", "Politics" ); //匹配所有仅由有一个单词组成的科目名 $alonewords = preg_grep("/^[a-z]*$/i", $subjects); ?>
6.3.2 전역 정규식 매칭
1. preg_match_all()
preg_match() 함수와 유사합니다. 세 번째 매개변수를 사용하면 가능한 모든 일치 항목이 입력됩니다. 이 함수는 전체 모듈을 반환합니다.
수식이 일치하는 횟수(0일 수 있음), 오류가 발생하면 False가 반환됩니다. 다음은 텍스트에 포함된 URL 링크 주소를 HTML 코드로 변환하는 예입니다. 코드 6.4는
preg_match_all() 함수의 사용 예입니다.
코드 6.4 텍스트에 있는 링크 주소를 HTML로 변환
<?php //功能:将文本中的链接地址转成HTML //输入:字符串 //输出:字符串 function url2html($text) { //匹配一个URL,直到出现空白为止 preg_match_all("/http:\/\/?[^\s]+/i", $text, $links); //设置页面显示URL地址的长度 $max_size = 40; foreach($links[0] as $link_url) { //计算URL的长度。如果超过$max_size的设置,则缩短。 $len = strlen($link_url); if($len > $max_size) { $link_text = substr($link_url, 0, $max_size)."..."; } else { $link_text = $link_url; } //生成HTML文字 $text = str_replace($link_url,"<a href='$link_url'>$link_text</a>",$text); } return $text; } //运行实例 $str = “这是一个包含多个URL链接地址的多行文字。欢迎访问http://www.jb51.net”; print url2html($str); /*输出结果 这是一个包含多个URL链接地址的多行文字。欢迎访问<a href='http://www.jb51.net'> http://www.jb51.net</a> */ ?>
2. 여러 줄 일치
POSIX에서는 일반 테이블 함수만으로는 복잡한 매칭 작업을 수행하기 어렵습니다. 예를 들어, 전체 파일(특히 여러 줄의 텍스트)에 대해 일치 검색을 수행합니다. ereg()를 사용하여 이 작업을 수행하는 한 가지 방법은 별도의 줄에서 수행하는 것입니다. 목록 6.5의 예는 ereg()가 INI 파일의 매개변수를 배열에 할당하는 방법을 보여줍니다.
코드 6.5 파일 내용의 여러 줄 일치
<?php $rows = file('php.ini'); //将php.ini文件读到数组中 //循环遍历 foreach($rows as $line) { If(trim($line)) { //将匹配成功的参数写入数组中 if(eregi("^([a-z0-9_.]*) *=(.*)", $line, $matches)) { $options[$matches[1]] = trim($matches[2]); } unset($matches); } } //输出参数结果 print_r($options); ?>
팁
이것은 단지 문제를 설명하기 위한 편의를 위한 것입니다. *.ini 파일을 구문 분석하는 가장 좋은 방법은 parse_ini_file() 함수를 사용하는 것입니다. 이 함수는 *.ini 파일을 큰 배열로 직접 구문 분석합니다.
6.3.3 정규식 치환
1. ereg_replace() 및 eregi_replace()
함수 프로토타입: 문자열 ereg_replace(string $pattern, string $replacement, string
$string)
string eregi_replace(string $pattern, string $replacement, string
$string)
ereg_replace()는 $string에서 패턴 문자열 $pattern을 검색하고 일치하는 결과를 바꿉니다.
$ 교체를 위해. $pattern에 패턴 단위(또는 하위 패턴)가 포함된 경우 $replacement의 "1" 또는 "$1" 형식의 위치는 차례로 이러한 하위 패턴으로 대체됩니다.
패턴과 일치하는 콘텐츠를 교체합니다. 그리고"
eregi_replace()와 ereg_replace()의 함수는 전자가 대소문자를 무시한다는 점을 제외하면 동일합니다. 코드 6.6은 이 함수의 적용 예입니다. 이 코드는 프로그램 소스 코드에서 간단한 정리 작업을 수행하는 방법을 보여줍니다.
코드 6.6 소스 코드 정리
<?php $lines = file('source.php'); //将文件读入数组中 for($i=0; $i<count($lines); $i++) { //将行末以“\\”或“#”开头的注释去掉 $lines[$i] = eregi_replace("(\/\/|#).*$", "", $lines[$i]); //将行末的空白消除 $lines[$i] = eregi_replace("[ \n\r\t\v\f]*$", "\r\n", $lines[$i]); } //整理后输出到页面 echo htmlspecialchars(join("",$lines)); ?>
2.preg_replace()
函数原型:mixed preg_replace (mixed $pattern,
mixed $replacement, mixed $subject [, int $limit])
preg_replace较ereg_replace的功能更加强大。其前三个参数均可以使用数组;第四个参数$limit可以设置替换的次数,默认为全部替换。代码6.7是一个数组替换的应用实例。
代码6.7 数组替换
<?php //字符串 $string = "Name: {Name}<br>\nEmail: {Email}<br>\nAddress: {Address}<br>\n"; //模式 $patterns =array( "/{Address}/", "/{Name}/", "/{Email}/" ); //替换字串 $replacements = array ( "No.5, Wilson St., New York, U.S.A", "Thomas Ching", "tom@emailaddress.com", ); //输出模式替换结果 print preg_replace($patterns, $replacements, $string); ?>
输出结果如下。
Name: Thomas Ching",
Email: tom@emailaddress.com
Address:
No.5, Wilson St., New York, U.S.A
在preg_replace的正则表达式中可以使用模式修正符“e”。其作用是将匹配结果用作表达式,并且可以进行重新运算。例如:
<?php $html_body = “<HTML><Body><H1>TEST</H1>My Picture<Img src=”my.gif”></Body></HTML>”; //输出结果中HTML标签将全部为小写字母 echo preg_replace ( "/(<\/?)(\w+)([^>]*>)/e", "'\\1'.strtolower('\\2').'\\3'", //此处的模式变量\\2将被strtolower转换为小写字符 $html_body); ?>
提示
preg_replace函数使用了Perl兼容正则表达式语法,通常是比ereg_replace更快的替代方案。如果仅对字符串做简单的替换,可以使用str_replace函数。
6.3.4 正则表达式的拆分
1.split()和spliti()
函数原型:array split
(string $pattern, string $string [, int $limit])
本函数返回一个字符串数组,每个单元为$string经正则表达式$pattern作为边界分割出的子串。如
果设定了$limit,则返回的数组最多包含$limit个单元。而其中最后一个单元包含了$string中剩余的所有部分。spliti是split的
忽略大小版本。代码6.8是一个经常用到关于日期的示例。
代码6.8 日期的拆分
<?php $date = "08/30/2006"; //分隔符可以是斜线,点,或横线 list($month, $day, $year) = split ('[/.-]', $date); //输出为另一种时间格式 echo "Month: $month; Day: $day; Year: $year<br />\n"; ?>
2.preg_split()
本函数与split函数功能一致。代码6.9是一个查找文章中单词数量的示例。
代码6.9 查找文章中单词数量
<?php $seek = array(); $text = "I have a dream that one day I can make it. So just do it, nothing is impossible!"; //将字符串按空白,标点符号拆分(每个标点后也可能跟有空格) $words = preg_split("/[.,;!\s']\s*/", $text); foreach($words as $val) { $seek[strtolower($val)] ++; } echo "共有大约" .count($words). "个单词。"; echo "其中共有" .$seek['i']. "个单词“I”。"; ?>
提示
preg_split()
函数使用了Perl兼容正则表达式语法,通常是比split()更快的替代方案。使用正则表达式的方法分割字符串,可以使用更广泛的分隔字符。例如,上面
对日期格式和单词处理的分析。如果仅用某个特定的字符进行分割,建议使用explode()函数,它不调用正则表达式引擎,因此速度是最快的。