分類:编程

Regular expression应用

最近在学习regular expression,刚巧项目上又有用到之处,故此把这两个我觉得挺有用的东西记录一下,以备后用:

1. 抽取SQL语句中Table的名字

一般SQL语句都是这个样子:

select *
from tables_a a
join tables_b b
on a.col = b.col

之前有个项目需要从上千个脚本之中抽取所有的Table名字出来,用人手做显然不可能,所以我最终决定使用regular expression。下面这两句一般来说已经足够:

(from)(\s)+([a-z_]+\.)*[0-9a-z_@]+
(join)(\s)+([a-z_]+\.)*[0-9a-z_@]+

第一句是将所有from后面的字符抽出来,第二句是将所有join后面的字符抽出来。MS SQL情况下,这种是没有问题的。但pl/sql的话,就有机会出现下面这种情况:

select *
from tables_a a, table_b b,
table_c c
where a.col = b.col
and b.col = c.col

遇上这种情况,只能用大包围方式,将所有有可能的字符也抽出来。

(,)(\s)*([a-z_]+\.)*[0-9a-z_@]+(\s)+[a-z0-9]+
([a-z_]+\.)*[0-9a-z_@]+(\s)+[a-z0-9]+(\s)*(,)

这大包围方式的坏处是会把column名字也抽出,到最后还是要人手看一次,不过也能省下不少时间。

2. 识别重复的pattern,并去重

识别重复pattern就是用上regular expression本身look ahead的功能。之前有个项目需要整理一些乱七八糟的数据,其中一项是从系统导出来的号码,不知为什么会自己重复,例如:

正常号码应该是:S1HK098723Y
导出来却变成:S1HK098723YS1HK098723Y

要识别这种变体不是很好弄,因为号码本身没有明确的分界符。但用regular expression一句就搞定

([a-zA-Z0-9]{5,})(\1)

之所以要限制第一组长度为5或以上,是因为要避免诸如00, XX等刚好有重复的字符。这个要因应情况修改。

Kali Linux下设立Wifi AP

在Kali Linux下设立Wifi AP的如下:

1. 安装所需package

apt-get install -y hostapd dnsmasq wireless-tools iw

2. 首先设定dnsmasq,这个提供DHCP和DNS服务功能


cat > /etc/dnsmasq.conf
log-facility=/var/log/dnsmasq.log
#address=/#/10.0.0.1
#address=/google.com/10.0.0.1
interface=wlan0
dhcp-range=10.0.0.10,10.0.0.250,12h
dhcp-option=3,10.0.0.1
dhcp-option=6,10.0.0.1
#no-resolv
log-queries
EOF

service dnsmasq start

3. 设定hostpad,这个会建立起Wifi AP服务


nano /etc/default/hostapd

#change this line
DAEMON_CONF="/etc/hostapd/hostapd.conf"

cat > /etc/hostapd/hostapd.conf
interface=wlan0
driver=nl80211
ssid=FreeWifi
channel=1
# Yes, we support the Karma attack.
#enable_karma=1
EOF

4. 接下来是设定NAT table,网上很多复杂设定,其实只需要开通FORWARD和MASQUERADE就可以了。当然也要开通ip_forward


iptables -t nat -F
iptables -F
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
iptables -A FORWARD -i wlan0 -o eth0 -j ACCEPT
echo '1' > /proc/sys/net/ipv4/ip_forward

5. 最后启动服务


ifconfig wlan0 up
ifconfig wlan0 10.0.0.1/24

airmon-ng check kill
service hostapd start

CSV parser by Regular Expression

Each column in a CSV file is seperated by a comma (,), if the field contains a comma inside, then it has to be bound by a pair of quote (“). Here below is an example:

0566000,1005660003,UG,MEDUU,MEDU_PGF,,MED,MBCHB,F,PGM,MEDUU,F,MBCHB,"M.B., CH.B.",UG

Therefore, we cannot simply parse the file by string.split(new char[] {,}). In this passage, I will use the regular expression instead to separate each column. First, we define the regular expression we use:

(((\"[^\"]*\")|([^\,\"]*))\,{1})|(\"[^\"]*\")|([^\,\"]*)

the source code would be:

string s = sr.ReadLine();
Regex Reg = new Regex(“(((\\\"[^\\\"]*\\\")|([^\\,\\\"]*))\\,{1})|(\\\"[^\\\"]*\\\")|([^\\,\\\"]*)", RegexOptions.IgnoreCase);
MatchCollection match = Reg.Matches(s);
string[] columns = new string[match.Count];
for (int j=0; j < match.Count ; j++)
{
columns[j] = match[j].Value;
}

So, we get the result.

Of course, you will then need to remove the comma or quote if you want. But at least we can parse them without any problem.

从BlogEngine.NET迁移到WordPress

刚刚完成从BlogEngine.NET迁移到WordPress的过程。为什么要迁移?很简单,PHP的成本实在是比ASP.NET划算太多了。外面web hosting的plan,同样配置的话php要比asp的便宜百分之30以上。像我现在用的就只要港币4元一个月,用ASP.NET的话根本做不到。当然,如果你是在家里用旧电脑架的服务器,当然就没什么区别了。话说回来,港币4元绝对比服务器的电费便宜。

迁移很简单,用过BE的人都知道,BE有export的功能,可以将所有文章+评论输出成BlogML格式。遗憾的是,WP本身没有自带Import BlogML格式的工具。于是,我们首先要去下载一个,跟着这个链接就对了:

http://www.kavinda.net/2008/10/23/migrating-from-dasblog-to-wordpress.html

文中本来说的是从DasBlog到Wordpress的迁移。但DasBlog也是输出到BlogML格式的,所以该工具对我们来说也适用。最后,当你Import完之后,只要将Category的名称(会变成一堆数字和字母)改回来就大功告成了。

MS SQL Server – Convert()

Syntax

Using CONVERT:

CONVERT data_type length , expression [ , style )

Arguments

expression

Is any valid Microsoft® SQL Server™ expression. For more information, see Expressions.

data_type

Is the target system-supplied data type, including bigint and sql_variant. User-defined data types cannot be used. For more information about available data types, see Data Types.

length

Is an optional parameter of ncharnvarcharcharvarcharbinary, or varbinary data types.

style

Is the style of date format used to convert datetime or smalldatetime data to character data (ncharnvarcharcharvarcharnchar, or nvarchar data types), or the string format when converting float, realmoney, or smallmoney data to character data (ncharnvarchar, charvarcharnchar, or nvarchar data types).

Without century (yy) With century (yyyy) Standard Input/Output**
0 or 100 (*) Default mon dd yyyy hh:miAM (or PM)
1 101 USA mm/dd/yy
2 102 ANSI yy.mm.dd
3 103 British/French dd/mm/yy
4 104 German dd.mm.yy
5 105 Italian dd-mm-yy
6 106 dd mon yy
7 107 Mon dd, yy
8 108 hh:mm:ss
9 or 109 (*) Default + milliseconds mon dd yyyy hh:mi:ss:mmmAM (or PM)
10 110 USA mm-dd-yy
11 111 JAPAN yy/mm/dd
12 112 ISO yymmdd
13 or 113 (*) Europe default + milliseconds dd mon yyyy hh:mm:ss:mmm(24h)
14 114 hh:mi:ss:mmm(24h)
20 or 120 (*) ODBC canonical yyyy-mm-dd hh:mi:ss(24h)
21 or 121 (*) ODBC canonical (with milliseconds) yyyy-mm-dd hh:mi:ss.mmm(24h)
126(***) ISO8601 yyyy-mm-dd Thh:mm:ss.mmm(no spaces)
130* Hijri**** dd mon yyyy hh:mi:ss:mmmAM
131* Hijri**** dd/mm/yy hh:mi:ss:mmmAM

Example

select CONVERT(varchar, getdate(), 120 )
2004-09-12 11:06:08

select replace(replace(replace(CONVERT(varchar, getdate(), 120 ),’-‘,”),’ ‘,”),’:’,”)
20040912110608

select CONVERT(varchar(12) , getdate(), 111 )
2004/09/12

select CONVERT(varchar(12) , getdate(), 112 )
20040912

select CONVERT(varchar(12) , getdate(), 102 )
2004.09.12

select CONVERT(varchar(12) , getdate(), 101 )
09/12/2004

select CONVERT(varchar(12) , getdate(), 103 )
12/09/2004

select CONVERT(varchar(12) , getdate(), 104 )
12.09.2004

select CONVERT(varchar(12) , getdate(), 105 )
12-09-2004

select CONVERT(varchar(12) , getdate(), 106 )
12 09 2004

select CONVERT(varchar(12) , getdate(), 107 )
09 12, 2004

select CONVERT(varchar(12) , getdate(), 108 )
11:06:08

select CONVERT(varchar(12) , getdate(), 109 )
09 12 2004 1

select CONVERT(varchar(12) , getdate(), 110 )
09-12-2004

select CONVERT(varchar(12) , getdate(), 113 )
12 09 2004 1

select CONVERT(varchar(12) , getdate(), 114 )
11:06:08.177

OpenCV2.0

安装

首先,OpenCV从2.0开始,用了CMake来产生Makefile,所以编译之前要先下载并安装CMake. 之后,下载并安装OpenCV。安装的时候选择Add path to All users。其他用预设值就可以了。安装之后打开CMake,source code输入C:\OpenCV2.0(你的安装路径),build folder随便输入一个你存放的位置。之后按configure,他会让你选你的编译器,用visual studio的话就选你正在用的vs版本吧。最后勾上你要生成的project,按generate就可以了。

编译

去build folder,打开OpenCV.sln就可以用visual studio正常编译了。如果是使用visual c++ express 2008的话,在编译的时候会提示缺少opm.h opmassem.h和vcomp.lib vcompd.lib这几个文件,找台有装visual studio 2008的电脑拷过来放在相应位置就可以了。

使用OpenCV

  • 打开VS2008,Tools->Options
  • Project and Solution -> VC++ Directories
  • 从Show directories中选择library
  • 添加C:\OpenCV2.0\lib
  • 从Show directories中选择include
  • 添加C:\OpenCV2.0\include\opencv

新建项目

  • Create a new C++ project
  • Project -> Properties
  • Configuration Properties -> Linker -> Input
  • 在Additional Dependency 输入以下档案:cxcore200.lib cv200.lib ml200.lib cvaux200.lib highgui200.lib
  • 成功编译

“Program failed to initialize properly 0xc0150002″ error

一般来说编译通过之后就可以执行,但使用Visual C++ express的朋友可能会出现以上错误。只要去下载并安装Microsoft Visual C++ 2008 Redistributable Package (X86)就可以解决这个问题了。

Cloud Computing 2

上文介绍了一些云计算的基本情况。说到云计算,就不得不提google这个将云计算发挥得淋漓尽致的公司。Google的网上办公(google apps)可以说是云计算的代表作,使用了google apps之后,公司不用再自己维护一堆服务器,使得公司的IT人员从繁琐的设定和高昂的维护费用中解放出来。有兴趣的人其实可以自己上网登记体验一下,25个账户以下的服务都是免费的。如果拥有自己的域名的话,更加可以通过设置CNAME来“个人化”自己的服务。比如说,我现在就有以下的服务:

http://mail.jiyunalex.com

http://docs.jiyunalex.com

http://calendar.jiyunalex.com

这三个分别是邮箱,文件和日历服务。所以呢,现在如果你发邮件到admin@jiyunalex.com的话,我就可以从下面这个画面登录进去检阅:

怎么样?cool吧。文件和日历功能都是类似的。当然,这些都是面向企业服务的,普通用户可能不会接触到。其实除了google,也有其他公司提供类似的云计算服务,其中一个就是www.dreamhostapps.com

dreamhostapps可以让用户免费寄存自己的网站,该网站提供了5个常用的服务,分别是WordPress, Drupal, ZenPhoto, phpBB和MediaWiki。用户登记之后就可以选择安装自己需要的服务。同样的,只要你有自己的域名,设定好一个CNAME之后,就相当于自己配置了一个服务器:

http://photo.jiyunalex.com

http://forum.jiunalex.com

通过这些服务,就可以省却自己架设和管理一台服务器的麻烦了。

Multipart form POST in C#

关于Multipart message的格式,可以参考W3C的网站,本文集中演示怎样用C#代码实现该类消息的传送。

[code:c#]

public static class FormUpload
    {
        public static HttpWebResponse MultipartFormDataPost(string postUrl, string userAgent, Dictionary<string, object> postParameters)
        {
            string formDataBoundary = “—————————–28947758029299″;
            string contentType = “multipart/form-data; boundary=" + formDataBoundary;

            byte[] formData = GetMultipartFormData(postParameters, formDataBoundary);

            return PostForm(postUrl, userAgent, contentType, formData);
        }
        private static HttpWebResponse PostForm(string postUrl, string userAgent, string contentType, byte[] formData)
        {
            HttpWebRequest request = WebRequest.Create(postUrl) as HttpWebRequest;

            if (request == null)
            {
                throw new NullReferenceException(“request is not a http request");
            }

            // Set up the request properties

            request.Method = “POST";
            request.ContentType = contentType;
            request.UserAgent = userAgent;
            request.CookieContainer = new CookieContainer();
            request.ContentLength = formData.Length;  // We need to count how many bytes we’re sending.

            using (Stream requestStream = request.GetRequestStream())
            {
                // Push it out there

                requestStream.Write(formData, 0, formData.Length);
                requestStream.Close();
            }

            return request.GetResponse() as HttpWebResponse;
        }

        private static byte[] GetMultipartFormData(Dictionary<string, object> postParameters, string boundary)
        {
            Stream formDataStream = new System.IO.MemoryStream();
            Encoding encoding = Encoding.Default;

            foreach (var param in postParameters)
            {
                if (param.Value is byte[])
                {
                    byte[] fileData = param.Value as byte[];

                    // Add just the first part of this param, since we will write the file data directly to the Stream

                    string header = string.Format(“–{0}\r\nContent-Disposition: form-data; name=\"{1}\"; filename=\"{2}\";\r\nContent-Type: application/octet-stream\r\n\r\n", boundary, param.Key, param.Key);
                    formDataStream.Write(encoding.GetBytes(header), 0, header.Length);

                    // Write the file data directly to the Stream, rather than serializing it to a string.

                    formDataStream.Write(fileData, 0, fileData.Length);
                }
                else
                {
                    string postData = string.Format(“–{0}\r\nContent-Disposition: form-data; name=\"{1}\"\r\n\r\n{2}\r\n", boundary, param.Key, param.Value);
                    formDataStream.Write(encoding.GetBytes(postData), 0, postData.Length);
                }
            }

            // Add the end of the request

            string footer = “\r\n–" + boundary + “–\r\n";
            formDataStream.Write(encoding.GetBytes(footer), 0, footer.Length);

            // Dump the Stream into a byte[]

            formDataStream.Position = 0;
            byte[] formData = new byte[formDataStream.Length];
            formDataStream.Read(formData, 0, formData.Length);
            formDataStream.Close();

            return formData;
        }

    }

[/code]

上面的FormUpload类目的是构造消息,下面就是FormUpload类的调用方法:

[code:c#]

        static void Main(string[] args)
        {
            // Read file data

            FileStream fs = new FileStream(“c:\\example.txt", FileMode.Open, FileAccess.Read);
            byte[] data = new byte[fs.Length];
            fs.Read(data, 0, data.Length);
            fs.Close();

            // Generate post objects

            Dictionary<string, object> postParameters = new Dictionary<string, object>();
            postParameters.Add(“user", “fdreader");
            postParameters.Add(“pass", “pl!mnsj@38“);
            postParameters.Add(“logfile", “example.txt");
            postParameters.Add(“example.txt", data);

            // Create request and receive response

            string postURL = @"http://bigbird.itsc.cuhk.edu.hk/etickettest/palm/attendance.asp“;
            string userAgent = “Someone";
            HttpWebResponse webResponse = FormUpload.MultipartFormDataPost(postURL, userAgent, postParameters);

            // Process response

            StreamReader responseReader = new StreamReader(webResponse.GetResponseStream());
            string fullResponse = responseReader.ReadToEnd();
            webResponse.Close();
            Console.Write(fullResponse);
            Console.ReadKey();
        }

[/code]

Cloud Computing

云计算(Cloud Computing)一词,起源于2004年左右,意指将所有软件和大部分的计算功能都放在一块云里面。客户端只需要安装一个云端程序(PC上一般已浏览器为主),就可以使用大量由云提供的服务。套句老话,这其实是一个瘦客户端-肥服务端模型,这个模型与十几二十年前的模型本质上是一样,但他们的出现原因和运作方法却不太一样。在十几年前,个人电脑刚刚兴起的年代,客户端的运算能力非常有限,而且当时人们对于服务商提供的服务没有什么要求,一般来说只要求文字和图片,对服务器的要求相对来说比较低。所以当年大部分的运算都是在服务端进行的。这就是当年的瘦客户端模型。后来,随着接入互联网的人数逐年提高,并且人们希望能得到更多的多媒体内容,服务器慢慢变得不胜负荷。这个时候由于个人电脑的速度也在不断提升。于是,就有人提出将一部分的运算放到客户端上运行,从而减低服务器的负荷。这就形成了肥客户端模型。可是到了现在,人们对于软件的需求又有了新的变化。随时可得和永不丢失的数据,即时更新的信息都是人们需要的东西。得益于高速发展的互联网,于是又有人提出将所有数据和运算重新归纳到服务端(云)上,客户只需要手持一台能上网的机器(手机,PDA,MID)就能随时随地访问到需要的数据和服务。在这种背景下,云计算就诞生了。

云计算有以下的特点:

  • 所有服务都是基于网络的(Web-based)。客户端只需要安装一个浏览器就可以访问所有服务。
  • 客户端不会储存任何资料和数据。所有东西都保存在服务器(云)上,这样用户无论何时何地在任何一台电脑上,都能访问到属于自己的个人数据。
  • 服务是通用的,就像Microsoft Office等通用软件一样,你可以做一些个性化的设置,但不会专门有大规模的customization。

对于企业用户来说,云计算可以省却维护服务器的麻烦。服务提供商为你提供了必要的软件和硬件维护,并且有24小时专人技术支持。企业能省下大量维护和升级的费用,所以云计算是很受欢迎的。