EL表达式语言及EL函数库 知识详解 学习笔记
本文查阅方法:
1、查阅目录 —— 查阅本文目录,确定想要查阅的目录标题
2、快捷“查找” —— 在当前浏览器页面,按键 “Ctrl+F” 按键组合,开启浏览器的查找功能,
在查找搜索框中 输入需要查阅的 目录标题,便可以直接到达 标题内容 的位置。
3、学习小结 —— 文中的学习小结内容,是笔者在学习之后总结出的,开发时可直接参考其进行应用开发的内容, 进一步加快了本文的查阅 速度。(水平有限,仅供参考。)
本文目录
学习小结
1、EL表达式简介
2、EL主要作用-- 获取数据
3、EL主要作用-- 执行运算
4、EL主要作用-- 获得web开发常用对象
5、EL主要作用-- 使用EL调用Java方法
6、EL自定义函数 开发步骤
7、标签库描述文件-- TLD文件模版及其元素的意义
8、EL自定义函数开发 Demo样例
9、EL注意事项
10、EL表达式保留关键字
11、SUN公司:EL函数库
12、EL函数库-- fn:toLowerCase
13、EL函数库-- fn:toUpperCase
14、EL函数库-- fn:trim
15、EL函数库-- fn:length
16、EL函数库-- fn:split
17、EL函数库-- fn:join
18、EL函数库-- fn:indexOf
19、EL函数库-- fn:contains
20、EL函数库-- fn:startsWith
21、EL函数库-- fn:replace
22、EL函数库-- fn:substring
23、EL函数库-- fn:substringAfter
24、EL函数库-- fn:escapeXml
学习小结
(1)在JSP页面中调用EL函数库的步骤
(a)在工程中导入JSTL包。
(b)在JSP页面中导入EL函数库。
<%@taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn"%>
(c)在需要的位置调用EL函数
${prefix:method(params)} 例如:${fn:length(list)}
(2)常用EL函数库列举
fn:toLowerCase
${fn:toLowerCase("Www.SinA.org")} 的返回值为字符串“www.sina.org”
${fn:toLowerCase("")}的返回值为空字符串
fn:toUpperCase
${fn:toUpperCase("Www.SinA.org")} 的返回值为字符串“WWW.SINA.ORG”
${fn:toUpperCase("")}的返回值为空字符串
fn:trim
${fn:trim(" www.sina.org ")} 的返回值为字符串“www.sina.org”。
fn:length
${fn:length(list) }
${fn:length("好好学习,天天向上!") } ——返回值10
fn:split
${fn:split("www.sina.org", ".")[1]}的返回值为字符串“sina”。
fn:join
${fn:join(fn:split("www,sina,org", ","), ".")} 的返回值为字符串“www.sina.org”
${fn:join(stringArray, “.")}返回字符串“www.sina.org” 。其中的stringArray为数组{"www","sina","org"}
fn:indexOf
${fn:indexOf("www.sina.org","in")} 的返回值为5
fn:contains -- fn:containsIgnoreCase
${fn:contains("aaaabbbcc","ab") } 的返回值为true
备注:fn:contains(string, substring)等价于fn:indexOf(string, substring) != -1。
fn:startsWith -- fn:endsWith
${fn:startsWith("www.sina.org","sina")}的返回值为false
fn:replace
${fn:replace("www sina org", " ", ".")}的返回值为字符串“www.sina.org”
fn:substring
${fn:substring("www.sina.org", 4, 8)} 的返回值为字符串“sina”
fn:substringAfter -- fn:substringBefore
${fn:substringAfter(“www.sina.org”, “.”)}的返回值为字符串“sina.org”。
fn:escapeXml
${fn:escapeXml("<a href=''>点点</a>")}
1、EL表达式简介
EL 全名为Expression Language。EL主要作用如下:
(1)获取数据:
EL表达式主要用于替换JSP页面中的脚本表达式,以从各种类型的web域 中检索java对象、获取数据。(例如:某个web域 中的对象,访问javabean的属性、访问list集合、访问map集合、访问数组)
(2)执行运算:
利用EL表达式可以在JSP页面中执行一些基本的关系运算、逻辑运算和算术运算,以在JSP页面中完成一些简单的逻辑运算。如:${user==null}
(3)获取web开发常用对象
EL 表达式定义了一些隐式对象,利用这些隐式对象,web开发人员可以很轻松获得对web常用对象的引用,从而获得这些对象中的数据。
(4)调用Java方法
EL表达式允许用户开发自定义EL函数,以在JSP页面中通过EL表达式调用Java类的方法。
2、EL主要作用-- 获取数据
使用EL表达式获取数据语法:“${标识符}”
(1)EL表达式语句在执行时,会调用pageContext.findAttribute()方法,用标识符为关键字,分别从page、request、session、application四个域中查找相应的对象,找到则返回相应对象,找不到则返回""。(注意,不是null,而是空字符串)。
示例:${user}
(2)EL表达式也可以很轻松获取JavaBean的属性,或获取数组、Collection、Map类型集合的数据,
例如:
${user.address.city}
${user.list[0]}:访问有序集合某个位置的元素
${map.key} : 获得map集合中指定key的值
(3)结合JSTL的foreach标签,使用EL表达式也可以很轻松迭代各种类型的数组或集合,例如迭代数组,迭代collection类型集合,迭代map类型集合。
Demo样例:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@page import="cn.itcast.domain.Person"%>
<%@page import="cn.itcast.domain.Address"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>el表达式获取数据</title>
</head>
<body>
<br/>----------------获取域中存的数据-------------------------<br/>
<%
String data = "abcd";
request.setAttribute("data",data);
%>
${data } <%--pageContext.findAttribute("data") ""--%>
<br/>----------------获取域中存的javabean的数据-------------------------<br/>
<%
Person p = new Person();
p.setName("aaaa");
request.setAttribute("person",p);
%>
${person.name }
<br/>----------------获取域中存的javabean中的javabean的数据---------------------<br/>
<%
Person p1 = new Person();
Address a = new Address();
a.setCity("上海");
p1.setAddress(a);
request.setAttribute("p1",p1);
%>
${p1.address.city }
<br/>----------------获取域中存的list集合中的数据-------------------------<br/>
<%
List list = new ArrayList();
list.add(new Person("aaa"));
list.add(new Person("bbb"));
request.setAttribute("list",list);
%>
${list['1'].name }
<br/>----------------获取域中map集合中的数据-------------------------<br/>
<%
Map map = new HashMap();
map.put("aa",new Person("aaaaa"));
map.put("bb",new Person("bbbbb"));
map.put("cc",new Person("ccccc"));
map.put("dd",new Person("ddddd"));
map.put("111",new Person("eeeee"));
request.setAttribute("map111",map);
%>
${map111.cc.name }
<br/>----------------其它常用的el表达式-------------------------<br/>
${pageContext.request.contextPath } // 很重要:获取当前Web应用的名称。
<a href="${pageContext.request.contextPath }/index.jsp">点点</a>
</body>
</html>
3、EL主要作用-- 执行运算
语法:${运算表达式},EL表达式支持如下运算符:(注:EL不能实现使用“+”合并字符串功能)
Demo样例:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>运算符示例</title>
</head>
<body>
<%
request.setAttribute("username","aaa");
request.setAttribute("password","124");
%>
${username=='aaa' && password=='123' }
<br/>----------------empty运算符-------------------------<br/>
<%
//request.setAttribute("list",null);
request.setAttribute("list",new ArrayList());
%>
${empty(list) }
<br/>----------------二元运算符-------------------------<br/>
${user!=null ? user.username : '' }
<br/>----------------二元运算符(数据回显)-------------------------<br/>
<%
request.setAttribute("gender","male");
%>
<!-- 回显 单选框数据 -->
<input type="radio" name="gender" value="male" ${gender=='male'?'checked':'' }>男
<input type="radio" name="gender" vlaue="female" ${gender=='female'?'checked':'' }>女
<!-- 回显 多选框数据(备注:本例中使用了EL函数库,在下文 中有讲解) -->
<%
request.setAttribute("likes",new String[]{"football","sing"});
%>
<input type="checkbox" name="likes" value="sing" ${fn:contains(fn:join(likes,","),"sing")?'checked':'' }>唱歌
<input type="checkbox" name="likes" value="dance" ${fn:contains(fn:join(likes,","),"dance")?'checked':'' }>跳舞
<input type="checkbox" name="likes" value="basketball" ${fn:contains(fn:join(likes,","),"basketball")?'checked':'' }>蓝球
<input type="checkbox" name="likes" value="football" ${fn:contains(fn:join(likes,","),"football")?'checked':'' }>足球
</body>
</html>
4、EL主要作用-- 获得web开发常用对象
EL表达式语言中定义了11个隐含对象,使用这些隐含对象可以很方便地获取web开发中的一些常见对象,并读取这些对象的数据。(前6个重点学习)
语法:${隐式对象名称} :获得对象的引用
隐含对象名称 描 述
pageContext 对应于JSP页面中的pageContext对象(注意:取的是pageContext对象。)【重点】
pageScope 代表page域中用于保存属性的Map对象【重点】
requestScope 代表request域中用于保存属性的Map对象【重点】
sessionScope 代表session域中用于保存属性的Map对象【重点】
applicationScope 代表application域中用于保存属性的Map对象【重点】
param 表示一个保存了所有请求参数的Map对象【重点:常用于数据回显】
paramValues 表示一个保存了所有请求参数的Map对象,它对于某个请求参数,返回的是一个string[]
header 表示一个保存了所有http请求头字段的Map对象
headerValues 表示一个保存了所有http请求头字段的Map对象,返回string[]数组。
注意:如果头里面有“-” ,例Accept-Encoding,则要headerValues[“Accept-Encoding”]
cookie 表示一个保存了所有cookie的Map对象
initParam 表示一个保存了所有web应用初始化参数的map对象
测试各个隐式对象时 的注意事项
(a) 测试headerValues时,如果头里面有“-” ,例Accept-Encoding,则要headerValues[“Accept-Encoding”]
(b) 测试cookie时,例${cookie.key}取的是cookie对象,如访问cookie的名称和值,须${cookie.key.name}或${cookie.key.value}
Demo样例:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>隐式对象</title>
</head>
<body>
${pageContext}
<br/>----------------使用el隐式对象访问指定的域-------------------------<br/>
<%
pageContext.setAttribute("aa","123");
%>
${aa }
${pageScope.aa }
${sessionScope.user!=null }
<br/>----------------获取保存了所有请求参数的Map对象-------------------------<br/>
${param.name } //多个同名name时,只能读到第一个
${paramValues.name[0] } //多个同名name时,只能读到所有的对象,然后按需取值
${paramValues.name[1] } //多个同名name时,只能读到所有的对象,然后按需取值
<br/>----------------获取请求头-------------------------<br/>
${header['Accept-Language'] }
<br/>---------------获取cookie-------------------------<br/>
${cookie.JSESSIONID.name }<br/>
${cookie.JSESSIONID.value }
${initParam.xx }
</body>
</html>
备注:EL表达式-- param 隐式对象实现数据回显的原理图解
5、EL主要作用-- 使用EL调用Java方法
EL表达式语法允许开发人员开发自定义函数,以调用Java类的方法。
示例:${prefix:method(params)}
在EL表达式中调用的只能是Java类的静态方法。并且这个Java类的静态方法需要在TLD文件中描述,才可以被EL表达式调用。
EL自定义函数用于扩展EL表达式的功能,可以让EL表达式完成普通Java程序代码所能完成的功能。
6、EL自定义函数 开发步骤
一般来说, EL自定义函数开发与应用包括以下三个步骤:
(1)编写一个Java类的静态方法
(2)编写标签库描述符(tld)文件,在tld文件中描述自定义函数。
(3)在JSP页面中导入和使用自定义函数
7、标签库描述文件-- TLD文件模版及其元素的意义
编写完标签库描述文件后,需要将它放置到<web应用>\WEB-INF目录中或WEB-INF目录下的除了classes和lib目录之外的任意子目录中。
TLD文件中各元素的含义
<uri> 元素用指定该TLD文件的URI,在JSP文件中需要通过这个URI来引入该标签库描述文件。
<function>元素用于描述一个EL自定义函数,其中:
(1) <name>子元素用于指定EL自定义函数的名称。
(2) <function-class>子元素用于指定完整的Java类名,
(3) <function-signature>子元素用于指定Java类中的静态方法的签名,方法签名必须指明方法的返回值类型及各个参数的类型,各个参数之间用逗号分隔。
TLD文件模版 my.tld 文件。
<?xml version="1.0" encoding="UTF-8" ?>
<taglib xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
version="2.0">
<description>A tag library exercising SimpleTag handlers.</description>
<tlib-version>1.0</tlib-version>
<short-name>SimpleTagLibrary</short-name>
<uri>/my</uri>
<function>
<name>filter</name>
<function-class>cn.itcast.demo.MyEL</function-class>
<function-signature>java.lang.String filter( java.lang.String )</function-signature>
</function>
</taglib>
8、EL自定义函数开发 Demo样例
Demo样例:
Java类的静态方法 :
public class MyEL {
//el函数
public static String filter(String message) {
if (message == null)
return (null);
char content[] = new char[message.length()];
message.getChars(0, message.length(), content, 0);
StringBuffer result = new StringBuffer(content.length + 50);
for (int i = 0; i < content.length; i++) {
switch (content[i]) {
case '<':
result.append("<");
break;
case '>':
result.append(">");
break;
case '&':
result.append("&");
break;
case '"':
result.append(""");
break;
default:
result.append(content[i]);
}
}
return (result.toString());
}
public static String add(String s1,String s2){ //合并字符串
return s1 + s2;
}
}
TLD描述文件:
<?xml version="1.0" encoding="UTF-8" ?>
<taglib xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
version="2.0">
<description>A tag library exercising SimpleTag handlers.</description>
<tlib-version>1.0</tlib-version>
<short-name>SimpleTagLibrary</short-name>
<uri>/my</uri>
<function>
<name>filter</name>
<function-class>cn.itcast.demo.MyEL</function-class>
<function-signature>java.lang.String filter( java.lang.String )</function-signature>
</function>
<function>
<name>add</name>
<function-class>cn.itcast.demo.MyEL</function-class>
<function-signature>java.lang.String add( java.lang.String,java.lang.String )</function-signature>
</function>
</taglib>
JSP页面调用:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib uri="/my" prefix="my" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>My JSP '4.jsp' starting page</title>
</head>
<body>
${my:filter("<a href=''>点点</a>") }
<%
User user = new User();
user.setUsername("aaaa");
//session.setAttribute("user",user);
%>
${user!=null?my:add("欢迎您:",user.username):''}
</body>
</html>
9、EL注意事项
EL表达式是JSP 2.0规范中的一门技术 。因此,若想正确解析EL表达式,需使用支持Servlet2.4/JSP2.0技术的WEB服务器。
注意:当有些Tomcat服务器如不能使用EL表达式时:
(1)升级成tomcat6
(2)在JSP中加入<%@ page isELIgnored="false" %>
10、EL表达式保留关键字
11、SUN公司:EL函数库
JSTL中的常用EL函数
由于在JSP页面中显示数据时,经常需要对显示的字符串进行处理,SUN公司针对于一些常见处理定义了一套EL函数库供开发者使用。
这些EL函数在JSTL开发包中进行描述,因此在JSP页面中使用SUN公司的EL函数库,需要导入JSTL开发包,并在页面中导入EL函数库,如下所示:
在页面中使用JSTL定义的EL函数:
<%@taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn"%>
12、EL函数库-- fn:toLowerCase
fn:toLowerCase函数将一个字符串中包含的所有字符转换为小写形式,并返回转换后的字符串,它接收一个字符串类型的参数,例如
fn:toLowerCase("Www.SinA.org") 的返回值为字符串“www.sina.org”
fn:toLowerCase("")的返回值为空字符串
13、EL函数库-- fn:toUpperCase
fn:toUpperCase函数将一个字符串中包含的所有字符转换为大写形式,并返回转换后的字符串,它接收一个字符串类型的参数。例如:
fn:toUpperCase("Www.SinA.org") 的返回值为字符串“WWW.SINA.ORG”
fn:toUpperCase("")的返回值为空字符串
14、EL函数库-- fn:trim
fn:trim函数删除一个字符串的首尾的空格,并返回删除空格后的结果字符串,它接收一个字符串类型的参数。需要注意的是,fn:trim函数不能删除字符串中间位置的空格。
例如,fn:trim(" www.sina.org ") 的返回值为字符串“www.sina.org”。
15、EL函数库-- fn:length
fn:length函数返回一个集合或数组大小,或返回一个字符串中包含的字符的个数,返回值为int类型。fn:length函数接收一个参数,这个参数可以是<c:forEach>标签的items属性支持的任何类型,包括任意类型的数组、java.util.Collection、java.util.Iterator、java.util.Enumeration、java.util.Map等类的实例对象和字符串。
如果fn:length函数的参数为null或者是元素个数为0的集合或数组对象,则函数返回0;如果参数是空字符串,则函数返回0。
Demo样例:
<%
request.setAttribute("arr",new String[5]);
%>
${fn:length(arr) }
<%
List list = new ArrayList();
list.add("aa");
list.add("bb");
request.setAttribute("list",list);
%>
<c:forEach var="i" begin="0" end="${fn:length(list)}">
${list[i] }
</c:forEach>
16、EL函数库-- fn:split
fn:split函数以指定字符串作为分隔符,将一个字符串分割成字符串数组并返回这个字符串数组。
fn:split函数接收两个字符串类型的参数,第一个参数表示要分割的字符串,第二个参数表示作为分隔符的字符串。
例如,fn:split("www.sina.org", ".")[1]的返回值为字符串“sina”。
17、EL函数库-- fn:join
fn:join函数以一个字符串作为分隔符,将一个字符串数组中的所有元素合并为一个字符串并返回合并后的结果字符串。fn:join函数接收两个参数,第一个参数是要操作的字符串数组,第二个参数是作为分隔符的字符串。
如果fn:join函数的第二个参数是空字符串,则fn:join函数的返回值直接将元素连接起来。
例如:假设stringArray是保存在Web域中的一个属性,它表示一个值为{"www","sina","org"}的字符串数组,则fn:join(stringArray, “.")返回字符串“www.sina.org”
fn:join(fn:split("www,sina,org", ","), ".") 的返回值为字符串“www.sina.org”
18、EL函数库-- fn:indexOf
fn:indexOf函数返回指定字符串在一个字符串中第一次出现的索引值,返回值为int类型。fn:indexOf函数接收两个字符串类型的参数,如果第一个参数字符串中包含第二个参数字符串,那么,不管第二个参数字符串在第一个参数字符串中出现几次,fn:indexOf函数总是返回第一次出现的索引值;如果第一个参数中不包含第二个参数,则fn:indexOf函数返回-1。如果第二个参数为空字符串,则fn:indexOf函数总是返回0。
例如:fn:indexOf("www.sina.org","in") 的返回值为5
19、EL函数库-- fn:contains
fn:contains函数检测一个字符串中是否包含指定的字符串,返回值为布尔类型。fn:contains函数在比较两个字符串是否相等时是大小写敏感的。
fn:contains函数接收两个字符串类型的参数,如果第一个参数字符串中包含第二个参数字符串,则fn:contains函数返回true,否则返回false。如果第二个参数的值为空字符串,则fn:contains函数总是返回true。实际上,fn:contains(string, substring)等价于fn:indexOf(string, substring) != -1。
忽略大小的EL函数:fn:containsIgnoreCase
20、EL函数库-- fn:startsWith
fn:startsWith函数用于检测一个字符串是否是以指定字符串开始的,返回值为布尔类型。
fn:startsWith函数接收两个字符串类型的参数,如果第一个参数字符串以第二个参数字符串开始,则函数返回true,否则函数返回false。如果第二个参数为空字符串,则fn:startsWith函数总是返回true。
例如:fn:startsWith("www.sina.org","sina")的返回值为false
与之对应的EL函数:fn:endsWith
21、EL函数库-- fn:replace
fn:replace函数将一个字符串中包含的指定子字符串替换为其它的指定字符串,并返回替换后的结果字符串。fn:replace方法接收三个字符串类型的参数,第一个参数表示要操作的源字符串,第二个参数表示源字符串中要被替换的子字符串,第三个参数表示要被替换成的字符串。
例如:fn:replace("www sina org", " ", ".")的返回值为字符串“www.sina.org”
22、EL函数库-- fn:substring
fn:substring函数用于截取一个字符串的子字符串并返回截取到的子字符串。fn:substring函数接收三个参数,第一个参数是用于指定要操作的源字符串,第二个参数是用于指定截取子字符串开始的索引值,第三个参数是用于指定截取子字符串结束的索引值,第二个参数和第三个参数都是int类型,其值都从0开始。
例如:fn:substring("www.sina.org", 4, 8) 的返回值为字符串“sina”
23、EL函数库-- fn:substringAfter
fn:substringAfter函数用于截取并返回一个字符串中的指定子字符串第一次出现之后的子字符串。fn:substringAfter函数接收两个字符串类型的参数,第一个参数表示要操作的源字符串,第二个参数表示指定的子字符串,
例如:fn:substringAfter(“www.sina.org”, “.”)的返回值为字符串“sina.org”。
与之对应的EL函数为:fn:substringBefore
24、EL函数库-- fn:escapeXml
例如: ${fn:escapeXml("<a href=''>点点</a>")}
25、EL函数库Demo样例
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>My JSP '5.jsp' starting page</title>
</head>
<body>
${fn:toLowerCase("AAAA") }
<%
request.setAttribute("arr",new String[5]);
%>
${fn:length(arr) }
<%
List list = new ArrayList();
list.add("aa");
list.add("bb");
request.setAttribute("list",list);
%>
<c:forEach var="i" begin="0" end="${fn:length(list)}">
${list[i] }
</c:forEach>
${fn:join(fn:split("www,itcast,cn",","),".") }
${fn:contains("aaaabbbcc","ab") }
${fn:escapeXml("<a href=''>点点</a>")}
<br/>---------------取出用户填写的爱好回显------------------------<br/>
<%
request.setAttribute("likes",new String[]{"football","sing"});
%>
<input type="checkbox" name="likes" value="sing" ${fn:contains(fn:join(likes,","),"sing")?'checked':'' }>唱歌
<input type="checkbox" name="likes" value="dance" ${fn:contains(fn:join(likes,","),"dance")?'checked':'' }>跳舞
<input type="checkbox" name="likes" value="basketball" ${fn:contains(fn:join(likes,","),"basketball")?'checked':'' }>蓝球
<input type="checkbox" name="likes" value="football" ${fn:contains(fn:join(likes,","),"football")?'checked':'' }>足球
</body>
</html>
敬请评论
(1)若您觉得本文 有用处 —— 请留言评论,以坚定其他 IT童鞋 阅读本文的信心。
(2)若您觉得本文 没用处 —— 请留言评论,笔者将会改进不足,以便为大家整理更加好用的笔记。
上一篇: 正则表达式 基础知识及常用案例 学习笔记