邢栋博客

邢栋博客,Action博客,记录工作和生活中的点点滴滴

php正则相关知识点笔记

正则 环视(零宽断言)

环视不匹配任何字符,只匹配文本中的特定位置。类似于\b,^,$那样。环视不会占用字符。

环视分为顺序和逆序两种。

顺序
(?=exp)位置的后面能匹配exp。例如(?=\d)当前位置右边是数字
(?!exp)位置的后面不能匹配exp。例如(?!\d)当前位置右边不是数字

逆序
(?<=exp)位置的前面能匹配exp。例如(?<=\d)当前位置左边是数字
(?<!exp)位置的前面不能匹配exp。例如(?<!\d)当前位置左边不是数字


(?=jeffrey)jeff 等价于  jeff(?rey)

例子
<?php
$string = '5345678986';
$pattern = '/(?!=\d)(?=(\d{3})+$)/';
$replacement  = ',';
echo  preg_replace($pattern, $replacement, $string);//5,345,678,986


贪婪与懒惰
贪婪 通常的行为是匹配尽可能多的字符
a.*b -- aabab -- 会匹配 aabab
懒惰 只要在后面加上一个问号?。这样.*? 就意味着匹配任意数量的重复,但是在能使整个匹配成功的前提下使用最少的重复。
a.*?b --- aabab  --  会匹配 aab和 ab


正则的引擎
是否支持忽略优先量词和分组捕获
支持的话是 NFA
不支持的话是 DFA

DFA文本主导   //  awk,egrep,flex,lex,msyql,procmail
NFA表达式主导 //  gnu,emacs,java,ergp,less,more,.net,perl,php,python,ruby,sed,vi



php pcre的主要函数

preg_grep    --------------  返回匹配模式的数组条目
preg_match --------------   执行一个正则表达式匹配
preg_match_all -------------- 执行一个全局正则表达式匹配
preg_filter --------------  执行一个正则表达式搜索和替换
preg_replace --------------   执行一个正则表达式的搜索和替换
preg_replace_callback --------------执行搜索并且使用一个回调进行替换
preg_split-------------- 通过一个正则表达式分隔字符串
preg_quote -------------- 转义正则表达式字符
preg_last_error-------------- 返回最后一个pcre正则执行产生的错误代码


php7下安装event扩展
1.先安装libevent

wget https://github.com/libevent/libevent/releases/download/release-2.1.8-stable/libevent-2.1.8-stable.tar.gz

tar -zxvf libevent-2.1.8-stable.tar.gz

cd  libevent-2.1.8-stable

./configure --prefix=/usr/local/libevent-2.1.8

make 

make install


2.再安装event扩展

wget http://pecl.php.net/get/event-2.3.0.tgz

tar -zxvf  event-2.3.0.tgz

cd event-2.3.0

/usr/local/php7/bin/phpize

./configure --with-php-config=/usr/local/php7/bin/php-config --with-event-libevent-dir=/usr/local/libevent-2.1.8/

make 

make install

然后在php.ini中加入 extension=event.so

重启php-fpm即可

php7内核读书笔记-第五章 php的编译与执行
php7内核读书笔记-第五章 php的编译与执行
opline指令-操作数类型
IS_CONST 常量,也称作字面量,比如$a=123,$a="hello",其中123,hello就是字面量
IS_CV 变量,比如$a=123,$b=3+$c,$a,$b,$c就是CV变量
IS_VAR PHP变量,比如$a=time(),time()的返回值就是IS_VAR类型
IS_TMP_VAR 临时变量,或者中间变量 $a="hello_".time(),  "hello".time()就是临时变量
IS_UNUSED 表示操作数没有使用
EXT_TYPE_UNUSED 表示返回值但是没有使用
php7内核读书笔记-第四章 内存管理
php7内核读书笔记-第四章 内存管理
引用计数
会使用引用计数机制的类型
type refcounted
simple types
string Y
interned string N(内部字符串,request完成后统一销毁释放 $a="hi")
array Y
imutable array N(不可变数组)
object Y
resource Y
reference Y

垃圾回收
ps:如果一个变量value的refcount减少到了0,那么此value可以被释放掉,不属于垃圾;如果一个变量value的refcount减少之后大于0,那么此value还不能被释放,此value可能成为一个垃圾(例子 $a=array(1);$a[]=$a;unset($a);)。
回收算法
php7内核读书笔记-第二章 SAPI
php-fpm的worker进程和master进程
worker进程-处理请求
每个worker进程会竞争地Accept请求,接收成功后解析fastcgi,然后执行相应的脚本,处理完成后关闭请求,继续等待新的连接,这个就是一个worker进程的生命周期。
1.等待请求
2.解析请求 
fastcgi请求到达后被worker接收,然后开始接收并解析请求数据,知道request数据完全到达
3.请求初始化
4.执行php脚本
5.关闭请求
master进程-管理进程
三种不同的进程管理模式
1.静态模式static
2.动态模式dynamic  默认
3.按需模式ondemand
信号
1.SIGINT/SIGTERM/SIGQUIT 
退出fpm在master收到退出信号后将向所有的worker进程发布退出信号,通知worker退出,然后master退出
2.SIGUSR1
重新加载日志文件
3.SIGUSR2
重启fpm,首先master也是回向所有的worker进行发出退出信号,等全部worker成功退出后,master会调用execvp()重新启动一个新的fpm,最后旧的master退出
4.SIGCHLD
php7的生命周期

php生命周期.png

1.模块初始化阶段(module startup)

这个阶段主要进行php框架、zend引擎的初始化操作。该阶段的入口函数为php_module_startup(),这个阶段一般是在SAPI启动时执行一次,对于FPM而言,就是在fpm的master进行启动时执行的。
该阶段的几个主要处理如下所诉:
1.激活SAPI:sapi_activate(),初始化请求信息SG(request_info)、设置读取POST请求的handel等,在module_startup阶段处理完成后将调用sapi_activate()
2.启动php输出 php_output_startup
3.初始化垃圾回收期:gc_globals_ctor(),分配zend_gc_globals内存
4.启动Zedn引擎 zend_startup,主要操作包括:
a.启动内存池 start_memory_manager()
b.设置一些util函数句柄(如zend_error_cb.zend_printf.zend_write)
c.设置Zend虚拟机编译、执行器的函数句柄zend_compile_file,zend_execute_ex,以及垃圾回收的函数句柄gc_collect_cycles
d.分配函数符号表(CG(function_table))、类符号表(CG(class_table))、常量符号表(EG(zend_constants))等,如果是多线程的话,还会分配编译器、执行器的全局变量
e.注册zend核心扩展:zend_startup_builtin_functions(),这个扩展是内核提供的,该过程将注册zend核心扩展提供的函数,比如strlen.define.func_get_args.class_exists等
f.注册zend定义的标准常量:zend_register_standard_constants(),比如E_ERROR.E_WARNING.E_ALL.TRUE.FALSE等
g.注册$GLOBALS超全局变量的获取handler
h.分配php.ini配置的存储符号表 EG(ini_directives)
5.注册php定义的常量,PHP_VERSION.PHP_ZTS.PHP_SAPI等
6.解析php.ini,解析完成后所有的php.ini配置保存在configuration_hash哈希表中。
7.映射php、zend核心的php.ini配置:根据解析出的php.ini,获取对应的配置值,将最终的配置插入EG(ini_directives) 哈希表
8.注册用户获取$_GET.$_POST.$_COOKIE.$_SERVER.$_ENV.$_REQUEST.$_FILES变量的handler
9.注册静态编译的扩展:php_register_internal_extensions_func()
10.注册动态加载的扩展:php_ini_register_extensions(),将php.ini中配置的扩展加载到php中
11.回调各扩展定义的module startup钩子函数,即通过PHP_MINT_FUNCTION()定义的函数
12.注册php.ini中禁用的函数、类,disable_functions.disbale_classes.

2.请求初始化阶段(request startup)
该阶段是在请求处理前每一个请求都会经历的一个阶段,对于fpm而言,是在worker进程accept一个请求并读取、解析完请求数据后的一个阶段。该阶段的处理函数为php_request_startup()
主要的处理有以下几个:
1.激活输出:php_output_activate()
2.激活zend引擎 zend_activate,主要操作如下所述
a.重置垃圾回收器 gc_reset()
b.初始化编译器:init_compiler()
c.初始化执行器:init_executor,将EG(function_table)、EG(clas_table)分配指向CG(function_table)、CG(class_table),所以在php的编译、执行同期,EG(function_table)与CG(function_table)、EG(clas_table)与CG(class_table)是同一个值;另外还会初始化全局变量符号表EG(symbol_table)、include过的文件符号表EG(included_files);
d.初始化词法扫描器:startup_scanner()
f.激活SAPI:sapi_activate()
g.回调各扩展定义的request startup钩子函数 zend_activate_modules()

3.执行脚本阶段(execute script)
该极端包括php代码的编译、执行两个核心阶段,这也是zend引擎最重要的功能。在编译阶段,php脚本将经历从php源代码抽象语法树再到opline指令的转化过程,最终生成的opline指令就是zend引擎可识别的执行指令,这些指令接着被执行器执行,这就是php代码解释执行的过程。这个接口的入口函数为php_execute_script()

4.请求关闭阶段(request shutdown)
在php脚本执行解释器执行完成后将进入请求关闭阶段,这个阶段将flush输出内容、发送http应答header头、清理全局变量、关闭编译器、关闭执行器等。另外,在该阶段将回调各扩展的request shutdown钩子函数。该阶段是请求初始化阶段的相反操作,与请求初始化时的处理一一对应

5.模块关闭阶段(module shutdown)

该阶段在SAPI关闭时执行,与模块初始化阶段对应,这个阶段主要是进行资源的清理、php各模块的关闭操作,同时,将回调各扩展的module shutdown钩子函数。具体的处理函数为 php_module_shutdown()


php7内核读书笔记-第一章 php基础架构
php7的变化
1.抽象语法树
2.Native TLS(线程局部存储)
使用Native TLS来保存线程的资源池,线程独享。
3.指定函数参数、返回值类型
4.zval结构的变化
php7将引用计数转移到了具体的value中。zval结构大小从24字节减少到了16字节
5.异常处理
6.HashTable变化
php中数组类型的内部实现结构。HashTable结构的大小从72字节减小到了56字节,数组元素Bucket结构也从72字节减小到了32字节
7.新的参数解析方式

创建一个简单的php7扩展

Php版本:7.0.0

首先进入php源码 ext 目录下

执行./ext_skel --extname=foobar    //foobar为我要创建的扩展模块

执行完毕后

cd ext/foobar/

vim config.m4


16 dnl PHP_ARG_ENABLE(foobar, whether to enable foobar support,

17 dnl Make sure that the comment is aligned:

18 dn1 [  --enable-foobar           Enable foobar support])


16、17、18行的dn1去掉,修改为


16 PHP_ARG_ENABLE(foobar, whether to enable foobar support,

17 Make sure that the comment is aligned:

18 [  --enable-foobar           Enable foobar support])


然后 vim foobar.c

找到

PHP_FUNCTION(confirm_foobar_compiled)

{

..............

}

在后面添加


PHP_FUNCTION(flyhello)

{

zend_string *strg;

strg = strpprintf(0, "hello world.");

RETURN_STR(strg);

}


然后找到


const zend_function_entry foobar_functions[] = {

     PHP_FE(confirm_foobar_compiled, NULL)       /* For testing, remove later. */

     PHP_FE_END  /* Must be the last line in foobar_functions[] */

 };


修改为


const zend_function_entry foobar_functions[] = {

     PHP_FE(flyhello,NULL)

     PHP_FE(confirm_foobar_compiled, NULL)       /* For testing, remove later. */

     PHP_FE_END  /* Must be the last line in foobar_functions[] */

 };

 


然后重新编译执行后,执行php -m 就可以看到foobar模块

新建php文件,内容<?Php echo flyhello();?>  执行后输出hello world.


优惠券
广告位-淘宝
最新微语