一个关于PHP正则匹配汉字的问题

起因是一个网友提了一个问题:

$pattern='/^\w+$/';
$str="人1994";
$ret = preg_match($pattern, $str, $matches);

他想着\w是应该能够匹配到中文字符“人”的,但是实际执行结果却是不能匹配。网友们给了各种解释和解决方案,总结下来有两个可行方案:

  1. 使用/u模式修饰符[1]
  2. 在pattern中使用unicode编码表示两种方案可以解决如上问题。

代码及输出如下:

<?php


$pattern='/^\w+$/';


$str="人1994";


$ret = preg_match($pattern, $str, $matches);


var_dump($ret);


var_dump($matches);





$pattern='/^\w+$/u';


$str="人1994";


$ret = preg_match($pattern, $str, $matches);


var_dump($ret);


var_dump($matches);





//From PHP 7.0


$pattern='/^\w+$/u';


$str="\u{4eba}1994";//人 =>  \u4eba


$ret = preg_match($pattern, $str, $matches);


var_dump($ret);


var_dump($matches);








Output for hhvm-3.18.5 - 3.22.0, 7.1.0 - 7.2.4


int(0)


array(0) {


}





int(1)


array(1) {


[0]=>


string(7) "人1994"


}





int(1)


array(1) {


[0]=>


string(7) "人1994"


}








Output for 5.6.0 - 5.6.30


int(0)


array(0) {


}





int(1)


array(1) {


[0]=>


string(7) "人1994"


}





int(0)


array(0) {


}





注意:第三个例子中的语法从PHP 7.0开始支持。[2] [3]

还有一个网友提出了一个观点[4]

这个不是 PHP 的锅,而是 PCRE 库的配置导致,\w 的匹配官方文档是这么说的 

A “word” character is any letter or digit or the underscore character, that is, any character which can be part of a Perl “word”. The definition of letters and digits is controlled by PCRE’s character tables, and may vary if locale-specific matching is taking place. For example, in the “fr” (French) locale, some character codes greater than 128 are used for accented letters, and these are matched by \w.

也就是说, PCRE 库的 character tables 配置会影响到\w 的匹配

目前没有验证TA所说的是否正确。

 

目前来看最好的方式就在在写pattern时使用模式修饰符/u。

 

References:

[1]https://secure.php.net/manual/zh/reference.pcre.pattern.modifiers.php

 

[2] PHP 7.0 has introduced the “Unicode codepoint escape” syntax.

https://secure.php.net/manual/en/migration70.new-features.php#migration70.new-features.unicode-codepoint-escape-syntax

 

[3] To support large Unicode ranges (ie: [\x{E000}-\x{FFFD}] or \x{10FFFFF}) you must use the modifier ‘/u’ at the end of your expression.

https://secure.php.net/manual/en/function.preg-match.php#90771

 

[4] https://www.v2ex.com/t/262150

https://stackoverflow.com/questions/1330693/validate-username-as-alphanumeric-with-underscores

 

 

HTTP访问控制(CORS, Cross-Origin Resource Sharing)

简单来说,CORS请求分为简单请求(非术语)和预检请求(Preflight Request)。

某些请求不会触发 CORS 预检请求。本文称这样的请求为“简单请求”,请注意,该术语并不属于 Fetch (其中定义了 CORS)规范。若请求满足所有下述条件,则该请求可视为“简单请求”:

使用下列方法之一:

GET

HEAD

POST

Fetch 规范定义了对 CORS 安全的首部字段集合,不得人为设置该集合之外的其他首部字段。该集合为:

Accept

Accept-Language

Content-Language

Content-Type (需要注意额外的限制)

DPR

Downlink

Save-Data

Viewport-Width

Width

Content-Type 的值仅限于下列三者之一:

text/plain

multipart/form-data

application/x-www-form-urlencoded

与前述简单请求不同,“需预检的请求”要求必须首先使用 OPTIONS   方法发起一个预检请求到服务器,以获知服务器是否允许该实际请求。”预检请求”的使用,可以避免跨域请求对服务器的用户数据产生未预期的影响。

 

当请求满足下述任一条件时,即应首先发送预检请求:

使用了下面任一 HTTP 方法:

PUT

DELETE

CONNECT

OPTIONS

TRACE

PATCH

人为设置了对 CORS 安全的首部字段集合之外的其他首部字段。该集合为:

Accept

Accept-Language

Content-Language

Content-Type (but note the additional requirements below)

DPR

Downlink

Save-Data

Viewport-Width

Width

Content-Type 的值不属于下列之一:

application/x-www-form-urlencoded

multipart/form-data

text/plain

对于预检请求,浏览器会先发送一个预检请求给服务端,服务端正常响应(服务器是否同意客户端继续请求)后才会发送实际请求。

References:

https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Access_control_CORS

https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS

对opencv的例子改进能识别出同一张图里面所有匹配的图像

/*
* A Demo to OpenCV Implementation of SURF
* Further Information Refer to “SURF: Speed-Up Robust Feature”
* Author: Liu Liu
* liuliu.1987+opencv@gmail.com
*/
#include “opencv2/objdetect/objdetect.hpp”
#include “opencv2/features2d/features2d.hpp”
#include “opencv2/highgui/highgui.hpp”
#include “opencv2/calib3d/calib3d.hpp”
#include “opencv2/nonfree/nonfree.hpp”
#include “opencv2/imgproc/imgproc_c.h”
#include “opencv2/legacy/legacy.hpp”
#include “opencv2/legacy/compat.hpp”

#include <iostream>
#include <vector>
#include <stdio.h>

using namespace cv;
using namespace std;

static void
flannFindPairs( const CvSeq*, const CvSeq* objectDescriptors,
const CvSeq*, const CvSeq* imageDescriptors, vector<int>& ptpairs )
{
int length = (int)(objectDescriptors->elem_size/sizeof(float));

cv::Mat m_object(objectDescriptors->total, length, CV_32F);
cv::Mat m_image(imageDescriptors->total, length, CV_32F);
// copy descriptors
CvSeqReader obj_reader;
float* obj_ptr = m_object.ptr<float>(0);
cvStartReadSeq( objectDescriptors, &obj_reader );
for(int i = 0; i < objectDescriptors->total; i++ )
{
const float* descriptor = (const float*)obj_reader.ptr;
CV_NEXT_SEQ_ELEM( obj_reader.seq->elem_size, obj_reader );
memcpy(obj_ptr, descriptor, length*sizeof(float));
obj_ptr += length;
}
CvSeqReader img_reader;
float* img_ptr = m_image.ptr<float>(0);
cvStartReadSeq( imageDescriptors, &img_reader );
for(int i = 0; i < imageDescriptors->total; i++ )
{
const float* descriptor = (const float*)img_reader.ptr;
CV_NEXT_SEQ_ELEM( img_reader.seq->elem_size, img_reader );
memcpy(img_ptr, descriptor, length*sizeof(float));
img_ptr += length;
}

// find nearest neighbors using FLANN
cv::Mat m_indices(objectDescriptors->total, 2, CV_32S);
cv::Mat m_dists(objectDescriptors->total, 2, CV_32F);
cv::flann::Index flann_index(m_image, cv::flann::KDTreeIndexParams(4)); // using 4 randomized kdtrees
flann_index.knnSearch(m_object, m_indices, m_dists, 2, cv::flann::SearchParams(64) ); // maximum number of leafs checked

int* indices_ptr = m_indices.ptr<int>(0);
float* dists_ptr = m_dists.ptr<float>(0);
for (int i=0;i<m_indices.rows;++i) {
if (dists_ptr[2*i]<0.6*dists_ptr[2*i+1]) {
ptpairs.push_back(i);
ptpairs.push_back(indices_ptr[2*i]);
}
}
}

/* a rough implementation for object location */
static int
locatePlanarObject( const CvSeq* objectKeypoints, const CvSeq* objectDescriptors,
const CvSeq* imageKeypoints, const CvSeq* imageDescriptors,
const CvPoint src_corners[4], CvPoint dst_corners[4] )
{
double h[9];
CvMat _h = cvMat(3, 3, CV_64F, h);
vector<int> ptpairs;
vector<CvPoint2D32f> pt1, pt2;
CvMat _pt1, _pt2;
int i, n;

flannFindPairs( objectKeypoints, objectDescriptors, imageKeypoints, imageDescriptors, ptpairs );

n = (int)(ptpairs.size()/2);
if( n < 4 )
return 0;

pt1.resize(n);
pt2.resize(n);
for( i = 0; i < n; i++ )
{
pt1[i] = ((CvSURFPoint*)cvGetSeqElem(objectKeypoints,ptpairs[i*2]))->pt;
pt2[i] = ((CvSURFPoint*)cvGetSeqElem(imageKeypoints,ptpairs[i*2+1]))->pt;
}

_pt1 = cvMat(1, n, CV_32FC2, &pt1[0] );
_pt2 = cvMat(1, n, CV_32FC2, &pt2[0] );
if( !cvFindHomography( &_pt1, &_pt2, &_h, CV_RANSAC, 5 ))
return 0;

for( i = 0; i < 4; i++ )
{
double x = src_corners[i].x, y = src_corners[i].y;
double Z = 1./(h[6]*x + h[7]*y + h[8]);
double X = (h[0]*x + h[1]*y + h[2])*Z;
double Y = (h[3]*x + h[4]*y + h[5])*Z;
dst_corners[i] = cvPoint(cvRound(X), cvRound(Y));
}

return 1;
}

int main(int argc, char** argv)
{
const char* object_filename = argc == 3 ? argv[1] : “box.jpg”;
const char* scene_filename = argc == 3 ? argv[2] : “box_in_scene.jpg”;

cv::initModule_nonfree();

IplImage* object = cvLoadImage( object_filename, CV_LOAD_IMAGE_GRAYSCALE );
IplImage* image = cvLoadImage( scene_filename, CV_LOAD_IMAGE_GRAYSCALE );
if( !object || !image )
{
fprintf( stderr, “Can not load %s and/or %s\n”,
object_filename, scene_filename );
exit(-1);
}

CvMemStorage* storage = cvCreateMemStorage(0);

cvNamedWindow(“Object Correspond”, 1);

static CvScalar colors[] =
{
{{0,0,255}},
{{0,128,255}},
{{0,255,255}},
{{0,255,0}},
{{255,128,0}},
{{255,255,0}},
{{255,0,0}},
{{255,0,255}},
{{255,255,255}}
};

IplImage* object_color = cvCreateImage(cvGetSize(object), 8, 3);
cvCvtColor( object, object_color, CV_GRAY2BGR );

CvSeq* objectKeypoints = 0, *objectDescriptors = 0;
CvSeq* imageKeypoints = 0, *imageDescriptors = 0;
int i;
CvSURFParams params = cvSURFParams(500, 1);

double tt = (double)cvGetTickCount();
cvExtractSURF( object, 0, &objectKeypoints, &objectDescriptors, storage, params );
printf(“Object Descriptors: %d\n”, objectDescriptors->total);

bool computer = true;

do
{
cvExtractSURF( image, 0, &imageKeypoints, &imageDescriptors, storage, params );
printf(“Image Descriptors: %d\n”, imageDescriptors->total);
tt = (double)cvGetTickCount() – tt;

printf( “Extraction time = %gms\n”, tt/(cvGetTickFrequency()*1000.));

CvPoint src_corners[4] = {{0,0}, {object->width,0}, {object->width, object->height}, {0, object->height}};
CvPoint dst_corners[4];

if( locatePlanarObject( objectKeypoints, objectDescriptors, imageKeypoints,
imageDescriptors, src_corners, dst_corners ))
{
for( i = 0; i < 4; i++ )
{
CvPoint r1 = dst_corners[i%4];
CvPoint r2 = dst_corners[(i+1)%4];
cvLine( image, cvPoint(r1.x, r1.y),
cvPoint(r2.x, r2.y ), colors[8] );
}

int width = dst_corners[1].x – dst_corners[0].x;
int height = dst_corners[2].y – dst_corners[0].y;

Rect selection(dst_corners[0], Size(width, height));
Mat roi(image, selection);
bitwise_not(roi, roi);
}
else
{
computer = false;
}

}while(computer);

cvShowImage( “Object Correspond”, image );

cvWaitKey(0);

cvDestroyWindow(“Object”);
cvDestroyWindow(“Object Correspond”);

return 0;
}

windows7恢复被误删的便笺

话说电脑这个东西借给普通用户用是往往会带来很大的麻烦,比如这个系统便笺[biàn jiān],被别人删了几次了。每次都很郁闷,但是因为种种原因也没有想着去恢复。这一次,是因为之前花了很大心血,做了不少的小摘抄,还没来得及整理成文档,结果被人一次性的给删除了。所以google一下看有什么恢复的方法。

其实方法很简单,因为windows 7系统自带有历史版本记录的功能。找到

C:\Users\taobig\AppData\Roaming\Microsoft\Sticky Notes 文件夹

(注:taobig为当前登录用户的用户名)

在文件夹中空白处(或者对这个文件夹)鼠标右键——“属性”——“以前的版本”

稍等片刻,现在系统正在帮你检索以前的版本,检索完后就会给你列出来。如下图

StickyNotes

参考来源:http://piscesfly.itpub.net/post/2874/498375

但是我发现我本机(X64 Windows 7)的Sticky Notes记录的目录与作者说的不一样)

 

附带:

微软给的教材,使用注册表来恢复误删的 Windows 7 便签提示

找到以下注册表子项:

HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Applets\StickyNotes

双击 PROMPT_ON_DELETE 注册表项。 数据框中,键入 00000001,然后单击确定

http://support.microsoft.com/kb/981026/zh-cn

 

 

SkyDrive的bug?!

昨天用SkyDrive传了两本txt的电子书,客户端一直显示在同步,但是一直没有显示成功。软件一直处于下图所示的同步状态,而且也不现实具体同步的进度。

我当时也没在意,以为是网络不稳定(你懂的!)。

但是今天仍然不能同步,于是我登陆网络版,试图利用浏览器在线上传文件。出现了如下的弹窗

这个弹窗终于让我知道是一位文件名中包含了“:”这个特殊字符。但是奇怪的是,这是一个中文的冒号。总所周知,在windows系统中文系统的Explorer中,文件名不能包含的是英文冒号“:”,但是用户是能建议包含中文冒号的文件名的,不知道为什么到了微软禁止上SkyDriver上传包含中文冒号的文件名的文件。最为过份的是客户端没有一点提示。

千呼万唤始出来的IE10 for windows 7

早就有报道微软放出了IE for windows 7的下载页面但是没有下载链接。前天晚上就传微软北京这边有负责人说将在13日放出版本。本以为是说的北京时间,昨天一直留意着,都没有看到发布。今天早上一看,倒是发布了。

http://ie.microsoft.com/testdrive/Info/Downloads/Default.html

这个地址,昨天白天查看时,只有两个链接,晚上时出现了这个链接

IE 10 on Windows 7 Preview
Released November 13th 2012

但是进去后,微软叫我们狠刷F5,泪奔啊。。。

今天进入倒是终于能下载了。支持多国语言,以及以下三个windows版本:

Windows 7 SP1 32-bit
Windows 7 SP1 64-bit
Windows Server 2008 R2 SP1 64-bit

 

安装过程很简单,就是注意一定要是打了SP1的系统,不然会提示“操作系统不受支持”。

 

IE 10外观上和IE9差不多,HTML5的跑分

注:虽然跑分不是唯一评判标准(比如:打死微软它也不会支持webM和ogg),但是通过这个测试还是能够看到清晰的看出浏览器对HMTL5的支持程度(比如:IE9就不支持File API、WebSocket,但是IE 10就支持了)。

权限问题导致windows 7 下CamStudio-Recorder不能保存录像

今天在使用CamStudio-Recorder时,发现一个非常恼火的问题,就是用CamStudio-Recorder录的屏幕视频不能保存,太奇怪了。因为在菜单选项中就没有保存这个选项,什么原因了?

因为我用的是windows 7 的系统,而且UAC是开启状态。所以怀疑是权限问题。以管理员权限运行软件,录像结束时,软件会弹出一个保存对话框,问题解决了。

权限不够,这是一个在windows 7 下很常见的问题。像7—zip不能保存设置,很多软件安装包双击安装时提示无法安装(一般都是没有权限创建临时文件夹,比如CamStudio-Recorder的安装文件就是这种情况,只是今天它的情况太特殊了——设置可以正常保存,但是无法创建视频文件)都是权限不够的问题。

关注 客户端软件更新

先看看我从三个地方截来的图片。本来是看见360软件管家有更新提示后,就跑到qq网站去瞧的,没想到qq的软件列表页面的更新提示没有更改,但是下载页面却悄然变化了。

这也是我一直有考虑的问题:现今的软件更新频率越来越快了,大的软件有稳定的服务器和技术支持,可以讲软件更新集成到软件本身中,但是对于小软件的更新却一直是个大问题。各种客户端的软件虽然是为了解决这个问题而诞生,但是这些软件本身肩负了太大的“使命”,很不纯粹了。所以一种新的方式要出现,像rss类似吧(我的想法),让软件更新不受制与某几家公司……

希望这一天早点到来。

[转载]Windows 8首个官方版本曝光

来源: http://www.sina.com.cn  2011年01月06日 10:37  驱动之家

在微软首席执行官史蒂夫·鲍尔默发表主题演讲之前,微软Windows部门主管Steven Sinofsky先为大家奉上了大餐前的开胃菜,演示了下一代Windows系统在ARM架构上的运行,并且宣布了微软新一代桌面电脑Surface 2.0。

尽管这是Windows 8首次官方露面,不过依然是犹抱琵琶半遮面。由于Windows 8仍处在早期开发阶段,所以Sinofsky并没有就其新功能做更多的阐述,亦或是要等到鲍尔默在晚些时候为大家揭晓。总之,从简单的演示中,我们可以看到,Windows 8的用户界面与Windows 7并没有明显变化

此次演示的Windows 8版本号为Build 6.2.7867,这也证实,Windows 8的内核架构为NT 6.2。相比内核为NT6.1的Windows 7,Windows 8并不会采用全新的架构,至少从内核版本中我们可以推测出这一点。也许Windows 8真的会在用户界面上大做文章?

之前有消息称,Windows 8将为32位和64位版本提供两个独立界面,其主要用户界面代号为“风”(Wind),支持拥有独立显卡的高端笔记本和台式机。这一切也许要等鲍尔默来揭晓了,我们会及时提供最新报道。

当前已知的最新Windows 8为Build 6.2.7904.0.101216-1845, 从其版本号可以看出,它编译于2010年12月16日。据悉,78XX是Windows 8的Milestone 1,79XX版本系列则是Windows 8的Milestone 2。如此说来,微软在CES上展示的是Windows 8 Milestone 1,而当前的开发已进入Milestone 2阶段。

微软的win7专业版学生优惠活动即将结束

目前微软校园先锋网站为会员提供的特价产品有:Windows7专业版(会员价199元,市场价1399元)、Office 2010 专业版(会员价149元,市场价4899元)。windows7的优惠活动会在12月31日结束。office2010优惠活动任然继续。

宣传视频:http://ms.shop.edu.cn/windows_home.php