当前位置: 首页 > 后端技术 > PHP

PHP基础系列正则表达式(一)

时间:2023-03-29 22:34:38 PHP

正则表达式的定义正则表达式是一种自定义的语法规则,描述字符排列的模式。由于正则表达式本身具有非常完备的语法体系,可以编写模式,提供了灵活直观的字符串处理方法,所以正则表达式又称为模式表达式。正则表达式的特点正则表达式并不是PHP独有的,JavaScript、Java、Perl、MySQL中的正则表达式都可以应用。正则表达式构造具有特定规则的模式,并将其与输入的字符串信息进行比较,实现字符串匹配、查找、替换、切分等操作。示例:“/^https?:\/\/(([a-zA-Z0-9_-])+(\.)?)*(:\d+)?(\/((\.)?(\?)?=?&?[a-zA-Z0-9_-](\?)?)*)*$/i"//匹配URL的正则表达式"/<(\S*?)[^>]*>.*?<\/\\1>|<.*?/>/i"//正则表达式匹配HTML标签"/\w+([-+.]\w)+*@\w+([-.]\w+)*\.\w+([-.]\w+)*/"//正则表达式匹配E-mail地址"/^]*\s*src\s*=\s*([']?)(?\S+)'?[^>l]*>$/"//匹配img标签注意正则表达式由普通字符组成,具有效率具有特殊含义的字符串。如果可以使用字符串函数完成任务,尽量不要使用正则表达式函数。对于一些复杂的操作,比如表单验证,统计一篇发表的文章有多少个句子,抓取一个网页中一定数量的页面等对各种格式的句子使用正则表达式和相关函数可以更好的实现正则表达式有一定的书写规则(语义),这是一种模式。如果正则表达式不与相应的正则表达式函数一起使用,那么正则表达式表达式就是字符串。正则表达式要实现匹配、查找、替换、拆分等功能,必须配合相应的正则表达式函数使用。PCRE库提供了两套PHP中支持正则表达式的函数库PCRE(PerlCompatibleRegularExpression)。与Perl语言兼容的正则表达式、以“preg_”为前缀命名的函数以及表达式应包含在分隔符中。POSIX(便携式操作系统接口)自PHP5.3.0起已被弃用。使用一组“ereg_”前缀函数。注1.两组函数库的功能相似,但执行效率不同。一般来说,实现同样的功能,PCRE库提供的正则表达式的效率略有优势。2.PCRE函数要求模式以定界符结束。3.与POSIX不同,PCRE扩展没有专门用于不区分大小写匹配的函数。相反,支持i(PCRE_CASELESS)模式修饰符来完成相同的工作。其他模式修饰符也可以用来改变匹配策略。4.POSIX函数从最左边开始寻找最长的匹配,但PCRE在第一个合法匹配后停止。如果字符串不匹配也没有关系,但如果它们匹配,结果和速度都会有所不同。为了说明这种差异,请考虑以下示例(来自JeffreyFriedl的书《精通正则表达式》)。使用模式one(self)?(selfsufficient)?要匹配字符串oneselfsufficient,PCRE将匹配self,但对于POSIX,结果将是整个字符串oneselfsufficient。两个子字符串都匹配原始字符串,但POSIX取最长的作为结果。函数比较POSIXPCREereg_replace()preg_replace()ereg()preg_match()eregi_replace()preg_replace()eregi()preg_match()split()preg_split()spliti()preg_split()sql_regcase()手册正则表达式语法规则正则表达式描述一个字符串匹配模式,通过该模式在特定的函数中对字符串进行匹配、查找、替换、拆分等操作。作为匹配模板,正则表达式由定界符、原子(普通字符,如a-z)、具有特殊功能的字符(称为元字符,如*、+、?等)和模式修饰符组成。由文本模式组成。示例:“/^https?\/\/(([a-zA-Z0-9_-])+(\.)?)*(\d+)?(\/((\.)?(\?)?=?&?[a-zA-Z0-9_-](\?)?)*)*$/i/"或'/^(.+?)<\/a.*?>$/sim'1。分隔符中使用两个斜杠“/”,模式置于它们之间以进行说明。2.原子使用<、a、href、=、'、"、/、>等普通字符和\t、\r、\n等转义字符。3.元字符使用[]、()、|、。,?,*,+等具有特殊含义的字符。4.使用的模式修饰符是定界符最后一个斜杠后的三个字符“s”,“i”,“m”。delimited字符定界符是其中之一PCRE不同于POSIX的特点。除字母、数字和反斜杠以外的字符都可以作为分隔符示例:{}、##、||、!!等/<\/w+>////使用反斜杠作为分隔符是合法的|(\d{3})-\d+|Sm//使用竖线“|”是合法的作为分隔符!^(?i)PHP[34]!//使用感叹号“!”是合法的asadelimiter{^\s+(\s+)?$}//使用花括号"{}"作为分隔符是合法的/href='(.*)'//非法分隔符,缺少结束分隔符1-\d3-\d3-\d4///非法定界符,缺少起始定界符注意,如果没有特殊要求,一般使用//作为定界符定界符是成对的,有一个起始符和一个结束符。原子原子是正则表达式中最基本的单位,每个模式必须至少包含一个原子。原子由所有未明确指定为元字符的打印字符(可以打印在屏幕上的字符)和非打印字符(看不见的字符)组成。简单的说,正则表达式中可以单独使用的字符称为原子,分为五类1.普通字符作为原子普通字符是写正则表达式时最常见的原子,包括所有大小写字母字符,所有数字,等,例如:a-z、A-Z、0-9。2、非打印字符(看不见的)为原子原子字符\x09含义描述+\cx匹配x指定的控制字符。例如,\c\M匹配Control-M或回车。x的值必须是A-Z或a-z之一,否则,c将被视为文字'c'字符。+\f匹配换页符。相当于\x0c和\cL+\n匹配一个换行符。相当于\x0a和\cJ+\r匹配回车。相当于\x0d和\cM+\t匹配一个制表符。等同于\x09和\cI+\v匹配一个垂直制表符。等同于\x0b和\cK3。通用字符类型用作原子。上面介绍的原子都是一个原子只能匹配一个字符。但有时我们需要一个原子来匹配一类字符。在正则表达式中,可以直接用一些表示范围的原子字符来描述含义\d匹配任意十进制数,相当于[0-9]\D匹配除十进制数以外的任意字符,相当于[^0-9]\w匹配任意数字、字母、下划线,等价于[0-9a-zA-Z_]\W匹配除数字、字母、下划线以外的任意字符,等价于[^0-9a-zA-Z_]\s匹配任意空白字符,相当于[\f\t\n\v\r]\S匹配除空白字符外的任意字符,相当于[^\t\f\n\v\r]4。将原子表([])自定义为原子。有的时候,以上六个一般性特征并不能满足我们的需要。我们需要自定义一类原子,比如奇数(1,3,5,7,9)。所以这时候,我们就需要自定义一类原子(称为类原子)。使用原子表“[]”可以定义一组相互相等的原子,并且只能匹配原子表中的一个字符。1表示匹配表中除原子外的任意字符,通常称为排除原子表。另外,在原子表中,可以用连字符(-)连接一组按ASCII码顺序排列的原子,可以简化书写。Example'/[apj]sp/'//可以匹配asp、jsp、PSP,只从原子表中选择一个atom'/[^apj]sp/'//可以匹配除asp、PSP、jsp以外的其他strings,suchasxsp,ysp,zsp,etc.'/0[xX][0-9a-fA-F]/'//可以匹配一个简单的十六进制数,比如0x2f,0X3AEor0x4aB,etc.5.一些特殊字符和元字符用作原子在正则表达式中,任何符号都可以用作原子,但如果该符号在正则表达式中有特殊含义,则可以使用转义符""取消其特殊含义,用作一个普通的角色。如"\.\*\+\?\(\<\>"""转义字符可以将有意义的字符转换为无意义的字符,也可以将无意义的字符转换为有意义的字符元字符元字符是具有特殊意义的字符,用于构建正则表达式,如“*”、“+”、“?”等。元字符不能单独出现,必须用来修饰原子。如果要在正则表达式中使用元字符本身,为了失去它的特殊含义,必须在其前面加上""来转义正则表达式的元字符元字符含义说明\*匹配0次,1次或它的前一个原子\+多次匹配其前一个原子的1倍或更多倍?匹配前一个原子的0次或1次。匹配除换行符外的任何字符|匹配两个或多个分支选项{n}表示前面的原子恰好出现n次{n,}表示前面的原子不少于n次出现{n,m}表示前面的原子最少出现n次,最多出现n次^或\A匹配输入字符串的开头(或多行模式下的行首,即在换行符后紧跟一个)$或\Z匹配输入字符串(或多行模式下的行尾,紧跟在换行符之后)\b匹配单词边界\B匹配单词边界以外的任何内容[]匹配方括号[^]中指定的任何原子匹配characterexcepttheatominthesquarebrackets,excludestheatomlist()匹配整个作为一个原子,即模式单元。可以理解为由多个单原子组成的大原子\xn匹配n,其中n为十六进制转义值。十六进制转义值必须是某两位数长。例如,`"\x41"`匹配`A`。`"\x041"`等同于`"\x04&1"`。ASCII编码可用于正则表达式。1.限定符限定符用于指定正则表达式的给定原子必须出现多少次才能满足匹配。限定词“*”、“+”、“?”、“{n}”、“{n,}”、“{n,m}”一共有六个,区别主要在于重复的次数匹配不同。其中“*”、“+”、“{n,}”限定符是贪心的,因为它们会尽可能匹配字面量。注意元字符“*”表示匹配前面的原子0次、1次或多次,也可以用“{0,}”来完成相同的匹配。“+”可以用“{1,}”来表示,“?”它可以用“{0,1}”表示。2.边界限制(断言)用于限制字符串或单词的边界范围,以获得更准确的匹配结果。元字符“^”或(“\A”)和“$”或(“\Z”)分别指代字符串的开头和结尾,而“\b”用于描述每个字符串的前面或后面字符串边界中的单词,与非单词边界的元字符“\B”相对。例如:有一个字符串“thisisatest”,使用边界限制如下:“/^this/”匹配这个字符是否以字符串“this”开头,匹配成功“/test$/”匹配这个字符是否以字符串"test"结尾,匹配成功"/\bis\b/"匹配这个字符串中是否包含"is"这个词,因为必须有分界"/\bis\b/"在字符串"is"的两边搜索字符串"is"时,左边必须没有边界,右边边界必须在右边,比如"this"匹配成功3.句点(.)在字符类之外,模式中的点可以匹配目标中的任何字符,包括非打印字符。但不匹配换行符(默认),相当于“[^\n]”(UNIX系统)或“[^\n\r]”(Windows系统)。但是如果设置了模式修饰符“s”,点也将匹配换行符。点的处理完全独立于^和$的处理。唯一的联系是它涉及换行符。注意1.`".*?""或`".+?"`组合匹配除换行符之外的任何字符串。例如:`"/.*?<\/b>/"`可以匹配任何以``、``标签开头并以任意换行符结尾的字符串4.ModeSelector(|)竖线字符“|”用于分隔多选模式,匹配正则表达式中的两个或多个选择之一。因为|的优先级是最低的,它的功能应该放在最后考虑。例如:灯|J2EE是指匹配LAMP,也可以匹配J2EE。自|优先级最低,并不意味着匹配'LAMP2EE'或'LAMJEE'。您也可以像这样使用“/Linux|Apache|MySQL|PHP/”,这意味着您可以从中匹配任何集合。5、模型单元模型单元是用元字符“()”将多个原子组成一个大原子。模式单元中的表达式将首先匹配。示例:'/(very)*good/'//可以匹配good、verygood、veryverygood6。反向引用反向引用是正则表达式应用点的重要组成部分。以()标记开头和结尾的多个原子既是一个独立的单元,又是一个子表达式(也叫子模式)。**在正则表达式模式或模式的一部分周围添加括号将导致关联的匹配项存储在临时缓冲区中,可以捕获以供以后使用**。每个捕获的子匹配项都按照正则表达式模式中从左侧遇到的顺序存储。存储子匹配的缓冲区从1开始,连续编号,最多99个表达式。可以使用\n访问每个缓冲区,其中n是特定缓冲区的一位或两位十进制数。例如:“\1”、“\2”、“\3”等形式的引号在正则表达式模式中使用时需要在前面加上反斜杠,以便再次转义反斜杠,例如:Referencesof形式为“\\1”、“\\2”、“\\3”等。如下图:'/^\d{4}\W\d{2}\W\d{2$}/'//这是一种匹配日期的格式,如2008-08/08或2008/08-08等'/^\d{4}(\W)\d{2}\\1\d{2$}/'//这是匹配日期的一种格式,比如2008-08-08或者2008/08/08等,当你想使用一个模式单元,不想存储匹配结果时,可以使用非捕获元字符“?:”、“?=”或“?!”省略保存关联的匹配项。请注意,在某些正则表达式中,有必要使用非存储模式单元,这可以更改其反向引用的顺序。`/(Windows)(Linux)\\2OS/`---使用“\2”再次引用第二个缓冲区中的字符串“Linux”`/(?:Windows)(Linux)\\1OS/`---使用“?:”忽略第一个子表达式的存储,所以“\1”指的是“Linux”7.模式匹配的优先级使用正则表达式时,需要注意匹配书序。通常,相同优先级的操作从左到右执行,不同优先级的操作先高后低。**顺序****元字符****描述**1\Escapesymbols2(),(?:),(?=),[]patternunitandatomtable3*,+,?,{n},{n,},{n,m}重复匹配4^,$,\b,\B,\A,\Z边界限制5|定界符(在最后一个斜杠“/”之后)。模式修饰符可以调整正则表达式的解释,扩展正则表达式在匹配、替换等操作中的一些功能;和模式修饰符可以结合使用,增强了正则表达式的处理能力。模式修饰符可以单独使用,也可以多个模式修饰符组合使用**模式修饰符****功能说明**i与模式匹配时不区分大小写m将字符串视为多行。以“^”和“$”开头的默认正则表达式将目标字符串视为单个“行”字符(即使它包含换行符)。如果在修饰符后面加上`"m"`,开始和结束将引用字符串的每一行,每行的开始是`"^"`,结束是`"$"`。s如果指定了子修饰符,则模式中的点元字符“.”匹配所有字符,包括换行符。即字符串被当作单行,换行符被当作普通字符。x模式中的空白将被忽略,除非它已被转义。e**仅在`preg_replace()`函数中,替换字符串做反向引用的正常替换,将其作为PHP代码求值,其结果替换搜索到的字符串**U该修饰符反转匹配次数的值被打开,所以它不是默认的重复,而是在“?”之后重复。**__这与Perl语言不兼容__**。也可以通过在模式中指定(U)修饰符或量词后跟问号“?”(例如.*?)来使用此选项。D模式中的美元元字符仅匹配目标字符串的末尾。如果没有这个选项,如果最后一个字符是换行符,美元符号也匹配子字符之前的内容。如果设置了m修饰符,则忽略此选项注意:模式“/WebServer/ix”可用于匹配字符串“webserver”,忽略大小写和空格。贪心匹配,在匹配成功的前提下,尽可能贪心的去匹配*,+,{n,},.*,比如:/a.*e/去匹配字符串"abcdfsdfsdfsesfdfsdfsesdfedfsdfses",因为'.*'是贪婪匹配。它会从这个字符串中匹配“abcdfsdfsdfsesfdfsdfsesdfedfsdfse”,从第一个a开始,到最后一个字母e结束,都属于'.*'的内容。如果想取消这种贪心模式,可以使用模式修饰符“U”或者使用.*?在模式中,并添加一个?后。*。为了兼容Perl正则函数,可能没有模式修饰符“U”,建议加上“?”在“.*”之后实现惰性模式(即非贪婪模式)。如果“U”和“?”同时使用,像这个“/a.*?e/U”,匹配“abcdfsdfsdfsesfdfsdfsesdfedfsdfse”,相当于又开启了贪心模式。惰性模式,在匹配成功的前提下,尽量少匹配(注意同上)模式“/^is/m”可以匹配字符串“this\nis\nais\ntest”中的'is',因为使用模式修饰符“m”将字符串视为多行,第二行出现“is”匹配成功。默认正则表达式以^开头并以'$'结尾,以将目标字符串视为单个“行”(甚至包括换行符)。注:看到这里你是不是一头雾水?是的,我也很困惑。不过没关系,秉承Learningbydoing的原则,在接下来的教程中,我会一一示范。更多文章请访问我的博客:Noapesexample/***截取汉字无乱码*@param$str*@paramint$start*@param$length*@paramstring$charset*@parambool|true$后缀*@returnstring|void*/functionmsubstr($str,$start=0,$length,$charset="utf-8",$suffix=true){if(function_exists("mb_substr"))returnmb_substr($str,$start,$length,$charset);elseif(function_exists('iconv_substr')){返回iconv_substr($str,$start,$length,$charset);}$re['utf-8']="/[x01-x7f]|[xc2-xdf][x80-xbf]|[xe0-xef][x80-xbf]{2}|[xf0-xff][x80-xbf]{3}/";$re['gb2312']="/[x01-x7f]|[xb0-xf7][xa0-xfe]/";$re['gbk']="/[x01-x7f]|[x81-xfe][x40-xfe]/";$re['big5']="/[x01-x7f]|[x81-xfe]([x40-x7e]|xa1-xfe])/";preg_match_all($re[$charset],$str,$match);$slice=join("",array_slice($match[0],$start,$length));如果($suffix)返回$slice;return$slice;}echomsubstr('哈哈哈你好',2,3,'gb2312');sdf?