first commit

This commit is contained in:
douboer
2025-09-17 16:08:16 +08:00
parent 9395faa6b2
commit 3ff47c11d5
1318 changed files with 117477 additions and 0 deletions

View File

@@ -0,0 +1,146 @@
# 正则表达式
## 112.匹配貌似邮件的正则表达式
/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/
这个正则表达式不能保证匹配都是合法的ip地址匹配成功只不过貌似ip地址的字串。比如它可以匹配一个合法的ip地址81.198.240.140同时也能匹配一个非法ip地址比如923.844.1.999。
下面解释他是如何工作的。正则开始的^符号是一个锚字符,用来匹配一个字串的开始。接着\d{1,3}匹配一个,两个或者三个连续数字。“\.”匹配一个点。最后的$也是一个锚字符匹配字段的结尾。使用^和$锚字符非常有必要否则的话诸如“foo213.3.1.2bar”一样的字串也会被匹配上。
这个正则可以简单的把开始部分\d{1,3}\.重复三次的到同样功能的表达式:
/^(\d{1,3}\.){3}\d{1,3}$/
## 113.测试数字是否在0-255的范围内
/^([0-9]|[0-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])$/
让我来看这个正则是如何工作的。此范围内的数可以为一个,两个或者三个数字。如果是一个数字,我们可以让它为任何[0-9]。如果是两个数字,我们也允许它为任何[0-9][0-9]的组合。然而如果它是三个数字的则他必须为100多或者200多的数。如果为100多的可以用1[0-9][0-9]匹配它。如果是200多的数字如果是小于250的可以用2[0-4][0-9]匹配。或者250-255的用25[0-5]匹配。
## 114.匹配IP地址
my $ip_part = qr|([0-9]|[0-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])|;
if ($ip =~ /^($ip_part\.){3}$ip_part$/) {
say "valid ip";
}
本正则组合了前面的两个。它用my $ip_part=qr/…/操作把正则表达式组合到一起,并且存到$ip_part变量中。接着用这个变量去匹配IP地址的四个部分。
## 115.检查字符串是否貌似email地址。
/.+@.+\..+/
这个正则确保字符串看起来像一个邮件地址。注意到这说的是"看起来像"。它不能保证确实是一个邮件地址。他的匹配过程是:首先匹配一些字符后跟个@符号,接着匹配任意字符然后到发现一个点,接着匹配更多个字符。如果这个匹配成功,那么这个字符串至少看起来就像个个邮件地址,他有@和.。
例如,admin@ijz.me可以匹配但是admin@ijzme不会匹配,因为他匹配不到点\.,这是必须的。
其实更可靠检测合法邮件地址的方法是是用Email::Valid 模块:
use Email::Valid;
print (Email::Valid->address('john@example.com') ? 'valid email' : 'invalid email');
## 116.检测字符串为十进制数。
检测字串是否是数字非常难。我基于正则并且在Perl Cookbook对其做了解释。
/^\d+$/
这个正则匹配一个或者更多的数字\d为了开始符^和结尾符$。但是它不能匹配诸如+3和-3这样的数字。让我们调整一下匹配他们
/^[+-]?\d+$/
此处[+-]?意思是在数字前匹配一个可选的正号或者负号。这个可以匹配+3或者-3但是还不能匹配-0.3。让我们加上它:
/^[+-]?\d+\.?\d*$/
我们在前一个正则的基础上加了\.?\d*,这匹配了一个可选的.在0或者其他数字后面。现在这个正则可以匹配诸如-0.3或者0.3的数字了。
更好的方式是是使用Regexp::Common模块它提供了各种非常有用的正则表达式。比如匹配一个整数你可以用$RE{num}{int}。
那么怎么匹配一个正16进制数字呢见下式
/^0x[0-9a-f]+$/i
这可以匹配十六进制前缀0x紧跟着数字。模式结尾的/i标志确保匹配是不区分大小写的。例如0x57af匹配0X5Fa也匹配但是97匹配不了由于他是一个十进制数。
当然最后是用模块$RE{num}{hex},它会支持负数,小数和逗点的数字组。
那么八进制呢?见下:
/^0[0-7]+$/
8进制数前缀是0其后紧跟八进制数字0-7。例如013匹配但是09不会匹配因为9不是一个合法的八进制数。
更好的方式是使用$RE{num}{oct},好处同上。
最后2进制
/^[01]+$/
二进制只包含0和1.例如0101101匹配但是210101不能因为2不是合法的二进制数字。
更好的方式是使用$RE{num}{bin}。
## 117.检测一个单词在字符串总出现了两次。
/(word).*\1/
这个正则匹配了word紧跟着任意字符随后是同样的word。此处word捕捉了word 分组1并用\1引用了分组1的内容因此这个和写作/word.*word/的模式一样。例如“silly things are silly”会匹配/(silly).*\1/但是“silly things are boring”不会匹配因为后面这个字串中silly没有重复。
## 118.给字串中的所有数字加1.
$str =~ s/(\d+)/$1+1/ge
此处我们使用替换操作符s///。他匹配所有的数字(\d+,把他们捕捉到组1接着把他们的值替换其值加1后的值。g标志确保它会知道字串中的所有的数字e标志使得$1+1作为一个Perl表达式执行。
例如“this 1234 is awesome 444”会被替换为“this 1235 is awesome 445”。
## 119. 提取HTTP头中用户客户端字串
/^User-Agent: (.+)$/
HTTP头以键值对的格式表示的。操作这些字串很简单你只要叫正则机保存值部分在$1组变量。
例如如果HTTP头包含
Host: localhost:8000
Connection: keep-alive
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_0_0; en-US)
Accept: application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
.
那么正则表示式将会提取Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_0_0; en-US)字串
## 120.匹配可打印字符。
/[ -~]/
这个一个非常巧妙的表达式。为了理解他看下ascii的说明。你可以发现空格符起始于0x20~符号是0x7e。所有的空格和~之间的字符的都是可以打印字符。这个正则表达式恰好匹配了这些。[ -~]定义了一个从空格到~的字符范围。这一直是我最喜欢的正则表达式。
/[^ -~]/
这个匹配恰好和[ -~]相反。
## 121.匹配两个HTML签之间的文本
m|([^<]*)|
这个正则表达式匹配了所有... 签之间的内容。此处技巧是([^<]*),它匹配会匹配尽可能多的字符知道发现一个<字符他会开始另一个标签
另外你也可以写成
m|(.*?)|
但是这个有点不一样了例如如果HTML内容是 hello 则第一个正则不能匹配但是第二个正则表达会匹配到hello由于(.*?)匹配尽可能少的内容知道发现这恰好是hello
但是我们一般不建议用正则表达式去匹配和处理HTML使用诸如HTML::TreeBuilder 模块去做这项工作是更明智的选择
## 122.替换所有的签为
$html =~ s|<(/)?b>|<$1strong>|g
此处我假设HTML内容保存在变量$html中。接着<(/)?b>匹配了起始和结束的签,捕捉可选的可选签在组$1接着用 或者 替换匹配的签这取决于匹配的是一个起始或者结束tag签。
## 123.提取正则表达式中所有匹配的部分。
my @matches = $text =~ /regex/g;
此处正则表达式在list上下文中使得他返回所有匹配。匹配的内容被放进@matches数组中
例如,下面的正则表达式提取了一个字符串中所有的数字。
my $t = "10 hello 25 moo 31 foo";
my @nums = $text =~ /\d+/g;
@nums 现在包含了(10, 25, 30)。