如图所示,此为一个简单的注册登录系统。我们利用JavaScript语言来实现它,在我们提交注册之后,“显示注册信息”这一栏中会给出详细的注册信息。
如图,我们可以对页面用右键选中“查看源文件”选项,可以查看到该页面的源代码。整个源码是利用JavaScript语言写成的。以下,我来详细剖析一下整个源码。
首先,整个源码是用HTML语言嵌入一些JS脚本来实现的。我们可以将其大致分为两个部分,<head>部分和<body>部分。<head>部分相当于android项目中的逻辑代码,而<body>部分则相当于android项目中的布局代码。中间唯一的难点应该就是正则表达式了,需要仔细去剖析。<body>部分又分为两个模块,一个是注册表框,一个是显示表框。
正则表达式 奥义:
正则表达式(英语:Regular Expression、regex或regexp,缩写为RE,正則表達式、正规表示法、常规表示法),计算机科学的一个概念。正则表达式使用单个字符串来描述、匹配一系列符合某个句法规则的字符串。在很多文本编辑器里,正则表达式通常被用来检索、替换那些符合某个模式的文本。
许多程序设计语言都支持利用正则表达式进行字符串操作。例如,在Perl中就内建了一个功能强大的正则表达式引擎。正则表达式这个概念最初是由Unix中的工具软件(例如sed和grep)普及开的。正则表达式通常缩写成“regex”,单数有regexp、regex,复数有regexps、regexes、regexen。
正则表达式的基本语法:
一个正则表达式通常被称为一个模式 (pattern),为用来描述或者匹配一系列符合某个句法规则的字符串。例如:Handel、Händel 和 Haendel 这三个字符串,都可以由“Ha|ä|(ae)ndel
”这个模式来描述。大部分正则表达式的形式都有如下的结构:
选择
| 竖直分隔符代表选择。例如“gray|grey
”可以匹配grey或gray。
数量限定
某个字符后的数量限定符用来限定前面这个字符允许出现的个数。最常见的数量限定符包括“+”、“?”和“*”(不加数量限定则代表出现一次且仅出现一次):
+ 加号代表前面的字符必须至少出现一次。(1次、或多次)。例如,“goo+gle
”可以匹配google、gooogle、goooogle等;
? 问号代表前面的字符最多只可以出现一次。(0次、或1次)。例如,“colou?r
”可以匹配color或者colour;
* 星号代表前面的字符可以不出现,也可以出现一次或者多次。(0次、或1次、或多次)。例如,“0*42
”可以匹配42、042、0042、00042等。
匹配
圆括号可以用来定义操作符的范围和优先度。例如,“gr(a|e)y
”等价于“gray|grey
”,“(grand)?father
”匹配father和grandfather。
上述这些构造子都可以自由组合,因此,“H(ae?|ä)ndel
”和“H(a|ae|ä)ndel
”是相同的。
精确的语法可能因不同的工具或程序而异。
正则表达式的一个简单实现:
Highlights:
在这段代码中大量地使用了C指针。在递归的每个阶段,如果存在某个字符匹配,那么在随后的递归调用中将执行指针算法(例如,regexp+1 and text+1),这样在随后的函数调用中,参数就是正则表达式的下一个字符和text的下一个字符。递归的深度不会超过匹配模式的长度,而通常情况下匹配模式的长度都是很短的,因此不会出现耗尽内存空间的危险。
2 函数match(regexp,text)用来判断文本中是否出现正则表达式;如果找到了一个匹配的正则表达式则返回1,否则返回0。
3 如果有多个匹配的正则表达式,那么函数将找到文本中最左边的并且最短的那个。
4 */
5 int match(char *regexp, char *text)
6 {
7 /*
8 如果正则表达式中的第一个字符是^(固定位置的匹配),那么匹配就一定要出现在字符串的开头。
9 也就是说,如果正则表达式是^xyz,那么仅当xyz出现在文本的开头而不是中间的某个位置时才会匹配成功。
10 在代码中通过把正则表达式的剩余部分与文本的起始位置而不是其他地方进行匹配来判断。
11 如果第一个字符不是^,那么正则表达式就可以在字符串中的任意位置上进行匹配。
12 在代码中通过把模式依次与文本中的每个字符位置进行匹配来判断。如果存在多个匹配,那么代码只会识别第一个(最左边的)匹配。
13 也就是说,如果则在表达式是xyz,那么将会匹配第一次出现的xyz,而且不考虑这个匹配出现在什么位置上。
14 */
15 if (regexp[0] == '^')
16 return matchhere(regexp+1, text);
17 /*
18 对输入字符串的推进操作是在一个do-while循环中进行的,这种结构在C程序中使用相对较少。
19 在代码中使用do-while而不是while通常会带来疑问:为什么不在循环的起始处判断循环条件,而是在循环末尾当执行完了某个操作之后才进行判断呢?
20 不过,这里的判断是正确的:由于*运算符允许零长度的匹配,因此我们首先需要判断是否存在一个空的匹配。
21 */
22 do
23 {
24 //大部分匹配工作是在matchhere函数中完成的
25 if (matchhere(regexp, text))
26 return 1;
27 }
28 while (*text++ != '/0');
29 return 0;
30 }
31
32 /*
33 这个函数将判断正则表达式与文本的开头部分是否匹配。
34 函数matchhere把正则表达式的第一个字符与文本的第一个字符进行匹配。
35 如果匹配失败,那么在这个文本位置上就不存在匹配,因此matchhere将返回0。
36 */
37 int matchhere(char *regexp, char *text)
38 {
39 /*
40 由于存在着一些特殊的情况,以及需要设置终止递归的条件。
41 因此实际的处理过程要更为复杂些最简单的情况就是,当正则表达式推进到末尾时(regexp[0] == '/0'),所有前面的判断都成功了。
42 那么这个正则表达式就与文本匹配。
43 */
44 if (regexp[0] == '/0')
45 return 1;
46 //如果正则表达式是一个字符后面跟着一个*,那么将会调用matchstar来判断闭包(closure)是否匹配。
47 if (regexp[1] == '*')
48 return matchstar(regexp[0], regexp+2, text);
49 //如果在正则表达式的末尾包含了一个$,那么仅当text此时位于末尾时才会匹配成。
50 if (regexp[0] == '$' && regexp[1] == '/0')
51 return *text == '/0';
52 /*
53 如果匹配成功了,函数将推进到正则表达式的下一个字符和文本的下一个字符继续进行匹配。
54 这是通过递归地调用matchhere函数来实现的。
55 */
56 if (*text!='/0' && (regexp[0]=='.' || regexp[0]==*text))
57 return matchhere(regexp+1, text+1);
58 return 0;
59 }
60
61 /*
62 函数matchstar(c, regexp, text)将尝试匹配重复的文本字符c,
63 从零重复开始并且不断累加,直到匹配text的剩余字符,如果匹配失败,那么函数就认为不存在匹配。
64 这个算法将识别出一个“最短的匹配”,这对简单的模式匹配来说是很好的,例如grep,这种情况下的主要问题是尽可能快地找到一个匹配。
65 而对于文本编辑器来说,“最长的匹配”则是更为直观,且肯定是更好的,因为通常需要对匹配的文本进行替换。
66 在目前许多的正则表达式库中同时提供了这两种方法,在《The Practice of Programming》一书中给出了基于本例中matchstar函数的一种简单变形
67 我们在后面将给出这种形式。
68 */
69 int matchstar(int c, char *regexp, char *text)
70 {
71 do
72 {
73 /* a * matches zero or more instances */
74 if (matchhere(regexp, text))
75 return 1;
76 }
77 while (*text != '/0' && (*text++ == c || c == '.'));
78 return 0;
79 }
正则表达式的实际运用:
1.验证用户名和密码:("^[a-zA-Z]\w{5,15}$")正确格式:"[A-Z][a-z]_[0-9]"组成,并且第一个字必须为字母6~16位;
2.验证电话号码:("^(\d{3.4}-)\d{7,8}$")正确格式:xxx/xxxx-xxxxxxx/xxxxxxxx;
3.验证身份证号(15位或18位数字):("^\d{15}|\d{18}$");
4.验证Email地址:("^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$");
5.只能输入由数字和26个英文字母组成的字符串:("^[A-Za-z0-9]+$") ;
6.整数或者小数:^[0-9]+\.{0,1}[0-9]{0,2}$
7.只能输入数字:"^[0-9]*$"。
8.只能输入n位的数字:"^\d{n}$"。
9.只能输入至少n位的数字:"^\d{n,}$"。
10.只能输入m~n位的数字:。"^\d{m,n}$"
11.只能输入零和非零开头的数字:"^(0|[1-9][0-9]*)$"。
12.只能输入有两位小数的正实数:"^[0-9]+(.[0-9]{2})?$"。
13.只能输入有1~3位小数的正实数:"^[0-9]+(.[0-9]{1,3})?$"。
14.只能输入非零的正整数:"^\+?[1-9][0-9]*$"。
15.只能输入非零的负整数:"^\-[1-9][]0-9"*$。
16.只能输入长度为3的字符:"^.{3}$"。
17.只能输入由26个英文字母组成的字符串:"^[A-Za-z]+$"。
18.只能输入由26个大写英文字母组成的字符串:"^[A-Z]+$"。
19.只能输入由26个小写英文字母组成的字符串:"^[a-z]+$"。
20.验证是否含有^%&',;=?$\"等字符:"[^%&',;=?$\x22]+"。
21.只能输入汉字:"^[\u4e00-\u9fa5]{0,}$"
22.验证URL:"^http://([\w-]+\.)+[\w-]+(/[\w-./?%&=]*)?$"。
23.验证一年的12个月:"^(0?[1-9]|1[0-2])$"正确格式为:"01"~"09"和"1"~"12"。
24.验证一个月的31天:"^((0?[1-9])|((1|2)[0-9])|30|31)$"正确格式为;"01"~"09"和"1"~"31"。
25.获取日期正则表达式:\d{4}[年|\-|\.]\d{\1-\12}[月|\-|\.]\d{\1-\31}日?
评注:可用来匹配大多数年月日信息。
26.匹配双字节字符(包括汉字在内):[^\x00-\xff]
评注:可以用来计算字符串的长度(一个双字节字符长度计2,ASCII字符计1)
27.匹配空白行的正则表达式:\n\s*\r
评注:可以用来删除空白行
28.匹配HTML标记的正则表达式:<(\S*?)[^>]*>.*?</>|<.*? />
评注:网上流传的版本太糟糕,上面这个也仅仅能匹配部分,对于复杂的嵌套标记依旧无能为力
29.匹配首尾空白字符的正则表达式:^\s*|\s*$
评注:可以用来删除行首行尾的空白字符(包括空格、制表符、换页符等等),非常有用的表达式
30.匹配网址URL的正则表达式:[a-zA-z]+://[^\s]*
评注:网上流传的版本功能很有限,上面这个基本可以满足需求
31.匹配帐号是否合法(字母开头,允许5-16字节,允许字母数字下划线):^[a-zA-Z][a-zA-Z0-9_]{4,15}$
评注:表单验证时很实用
32.匹配腾讯QQ号:[1-9][0-9]\{4,\}
评注:腾讯QQ号从000 0 开始
33.匹配中国邮政编码:[1-9]\d{5}(?!\d)
评注:中国邮政编码为6位数字
34.匹配ip地址:((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)。
一个注册登录系统的JS源码:
2 <!--
3 头部说明文件
4 HT制作声明
5 -->
6 <head>
7 //这里给网页设置标题"欢迎注册",加一个icon也是可以的
8 <title>欢迎注册</title>
9 <!--里面实现的类-->
10 //这里将脚本语言设置为javascript
11 <script language="javascript" type="text/javascript">
12 /*
13 function isEmail( str ){
14 var myReg = /^[-_A-Za-z0-9]+@([_A-Za-z0-9]+\.)+[A-Za-z0-9]{2,3}$/;
15 if(myReg.test(str)) return true;
16 return false;
17 }
18 */
19 //点击"提交"按钮之后,响应的函数
20 function mysubmit(){
21 //获取用户名,以下相同
22 var username=document.getElementById("username");
23 //密码
24 var password=document.getElementById("password");
25 //确认密码
26 var conpassword=document.getElementById("conpassword");
27 //联系方式
28 var telephone=document.getElementById("telephone");
29 //邮箱
30 var email=document.getElementById("email");
31 var s=/^[^\s]+$/;
32 //当它们都为空的时候弹出报错
33 if(!s.test(username.value)){
34 //弹出的对话框的内容,设置焦点到用户名的EditText中
35 alert("用户名为空");
36 username.focus();//光标一定不能放在弹出的信息框上,否则会出现死循环
37 return false;
38 }
39 //用户名超过了12位报错,密码在6到20之外报错
40 if(!/^[^\s]{1,12}$/.test(username.value)){
41 alert("您申请的用户名超过12");
42 username.focus();
43 return false;
44 }
45 if(!s.test(password.value)){
46 alert("密码为空");
47 password.focus();
48 return false;
49 }
50 //用户名超过了12位报错,密码在6到20之外报错
51 //password.value.length<6||password.value.length>20
52 if(!/^[^\s]{6,20}$/.test(password.value)){
53 alert("您申请的密码不在6到20个字符之间");
54 password.focus();
55 return false;
56 }
57 if(!s.test(conpassword.value)){
58 alert("确定密码为空");
59 conpassword.focus();
60 return false;
61 }
62 //判断两次密码是否一致
63 //password.value!=conpassword.value
64 //ereg( "sc ", "dafsc ")
65 //!(password.value.exec(conpassword.value))
66 if(password.value!=conpassword.value){
67 alert("您输入的两次密码不一致");
68 conpassword.focus();
69 return false;
70 }
71 if(!s.test(telephone.value)){
72 alert("联系方式为空");
73 telephone.focus();
74 return false;
75 }
76 if(!/^1[0-9]{10,10}$/.test(telephone.value)){
77 alert("联系方不合法,仅数字以1开头的11位数字");
78 return false;
79 }
80 if(!s.test(email.value)){
81 alert("邮箱为空");
82 email.focus();
83 return false;
84 }
85 //检验邮箱是否合法
86 if(!/^\w+@\w+\.(.+)$/.test(email.value)){
87 alert("邮箱不合法");
88 email.focus();
89 return false;
90 }
91 //其他注册成功
92 alert("恭喜您!注册成功!!!注册的用户:"+username.value);
93 document.execCommand('Refresh');
94 //return ture;
95
96 }
97
98 </script>
99 </head>
100 <!--
101 要求注册的用户名不超过12个字符
102 密码不能少于6个字符也不大于20个字符
103 检验邮箱的正确性
104 -->
105 <body>
106 <!-- 注册表框 -->
107 <fieldset><legend>欢迎注册</legend>
108 <form id="myform" name="myForm" action="" submit="mysubmit()">
109 <table border="1" align="center">
110 <tr>
111 <th colspan="3">用户注册</th>
112 </tr>
113 <tr>
114 <th>用户名:</th>
115 <td><input id="username" type="text" value=""/></td>
116 <td>*用户名最多不能超过12个字符</td>
117 </tr>
118 //注释中,用户名被块引用
119 <!--
120 <blockquote>用户名为:username.value</blockquote>
121 -->
122 //text的类型与passpord的类型的不同点在于,一个是可以见的,一个是用*隐藏的
123 <tr>
124 <th>新密码:</th>
125 <td><input id="password" type="password" value=""/></td>
126 <td>*用户密码不少于6个字符也不超过20个字符</td>
127 </tr>
128 <tr>
129 <th>确认密码:</th>
130 <td><input id="conpassword" type="password" value=""/></td>
131 <td>*该密码请输入与上一次相同的</td>
132 </tr>
133 <tr>
134 <th>联系方式:</th>
135 <td><input id="telephone" type="text" /></td>
136 //&bsp指代一个空白
137 <td> </td>
138 </tr>
139 <tr>
140 <th>邮 箱:</th>
141 <td><input id="email" type="text" /></td>
142 <td> </td>
143 </tr>
144 <tr>
145 //按钮都有固定的设置,这里,将"提交"按钮绑定监听,点击之后,响应mysubmit()函数
146 <td><input type="submit" name="Submit" value="提交" onClick="javascript:mysubmit();return false;"/></td>
147 <td><input type="reset" name="reset" value="重置"/></td>
148 <td><input type="button" name="exitbutton" value="退出"/></td>
149 </tr>
150 </table>
151 </form>
152 </fieldset>
153 //这里是<body>部分的第二大块,显示表框
154 <!-- 显示表框 -->
155 <fieldset><legend>显示注册信息</legend>
156 <form id="showForm" name="showForm" action="">
157 <table border="0" align="center">
158 <tr>
159 <td><script type="text/javascript">
160 var x=document.getElementById("myForm");
161 document.write("文档包含: " + document.forms.length + " 个表单。")
162 </script></td>
163 </tr>
164 </table>
165 </form>
166 </fieldset>
167 </body>
168 </html>