PHP에는 두 가지 정규식 함수 라이브러리 세트가 있습니다. 한 세트는 PCRE(Perl Compatible Regular Expression) 라이브러리에서 제공됩니다. PCRE 라이브러리는 "preg_" 접두사가 붙은 함수를 사용하여 Perl과 동일한 구문 규칙을 사용하여 정규식 패턴 일치를 구현합니다. 다른 세트는 POSIX(Portable Operation System 인터페이스) 확장 라이브러리에서 제공됩니다. 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
현재 시간 : 오후 1시 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(string $pattern, array $input)
preg_grep() 함수는 주어진 $pattern 패턴과 일치하는 $input 배열의 셀을 포함하는 배열을 반환합니다. Preg_grep()은 또한 입력 배열 $input의 각 요소에 대해서만 일치를 수행합니다. 목록 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链接地址的多行文字。欢迎访问//m.sbmmt.com”; print url2html($str); /*输出结果 这是一个包含多个URL链接地址的多行文字。欢迎访问<a href='//m.sbmmt.com'> //m.sbmmt.com</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을 검색하고 일치하는 결과를 $replacement로 바꿉니다. $pattern에 패턴 단위(또는 하위 패턴)가 포함된 경우 $replacement의 "1" 또는 "$1" 형식의 위치는 이러한 하위 패턴과 일치하는 콘텐츠로 대체됩니다. 그리고"
<?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()函数,它不调用正则表达式引擎,因此速度是最快的。
更多PHP 正则表达式常用函数使用小结相关文章请关注PHP中文网!
相关文章: