- 浏览: 96697 次
- 性别:
- 来自: 苏州
文章分类
最新评论
-
jameswolf:
补肾啊!冬天多喝,但是补只是后招,别漏才是真理,呵呵
朋友告诉我的神粥秘方 -
wa327114652:
很想学习,但能再详细点吗?
for java beginner 5-2 - 自己实现枚举-下 -
superlittlefish:
不错,简单易懂.一直在看你的blog,感觉反射写的挺好的.让我 ...
for java beginner 15 下java反射在框架里的应用 读取properties文件
001 regex 概述
★正则表达式及其作用
老的: ? >> once * >> zero or more
正则表达式类似,强大了点,灵活了点
正则表达式[翻译的不好]
regular expression
英文的意思是:符合某种规则的表达式
可以把正则表达式当一种语言[文本模式]
去匹配文本串,或者说文本串来匹配模式
正则表达式由一些元字符组成,
这些一组成,那么这个正则表达式就不是文本内容了,
而是一种文本模式
元字符(metacharacter)特殊字符
比如你要在一堆文字里查找这东西
要么5个数字 要么5个数字后加
连字符再加4个数字 共十个
可以用
\d{5}(-\d{4})?
正则表达式里的 ? 表示 once or not at all
重要重要 仅仅表示 紧考在 ? 前面 的元素项哦
所以我用()!!
-----------------
再说一个例子:
关于 ? 的
abc? 匹配 ab 或者 abc
a(bc)? 匹配 a 或者 abc
-----------------
重要:刚刚看见() 的作用了
() 还有一个更厉害的作用:
他 括起来的东西也叫一个 "子匹配"
除了可以得到 整个 正则表达式的匹配结果外,
还可以单独得到每个 子匹配 所匹配的结果
就是说可以用() 把一个长的 正则表达式 分为多个子表达式
多个子表达式匹配的内容按照他们在正则表达式 左到右 出现
的顺序存储在缓存区里,这叫"捕获"
这样说肯定不懂,说个需求
我现在要匹配555香烟,三个数字要一样
\d{3}这样的话123 456 都出来了,不要!!
---
上面说完 捕获, 捕获好了后可以在整个表达式中位于
这个括号后的地方"反向引用"
第一个() 用 \1 表示
第二个() 用 \2 表示
...
所以要匹配2个相同的连续数字字符的正则表达式为
(\d)\1
刚刚的三五香烟
(\d)\1{2} [就是说\1还得出来2次哦,必须2次哦]
要匹配这样的数字 1221 3553 7887 个位千位一样 十位百位一样
(\d)(\d)\2\1
=============
来看看作用:
1
测试字串是不是匹配某个模式,看看输入的数据是不是有效
2
将一堆文本满足某一表达模式的文本内容替换或者删除[既替换为空即可]
比如在一堆文本中 把19XX的内容换成20XX [XX不变]
不可以简单的把19换20哦,否则1919 要变2020 ,而需求是1919变2019
如果是那么简单 word就可以解决问题了,呵呵
3
一堆里 搜索 某一类特征的文本内容
精确搜索:搜索一个具体的文本 .例如用 word 软件[必须提供精确内容哦]
而正则搜索: 可以搜索出某一类的文本[提供模式就可以了]
--------
顺便说一下为什么要用TXT CSV
TXT存在是因为他太通用了,什么软件都可以打开查看
CSV是因为有时候TXT的一个整体里有空格什么的,很难分,所以用","了
--------
说一个例子
在一文本里有上亿行数据[其中一行是这样的]
0.0.0.0 0.255.255.255 IANA 未知地区
现在要把这上亿条记录放DB里,三列,一二列是IP 第三列是说明
现在没有DB不认识,DB说我要根据什么分呢?空格?说明里也有空格啊
所以先要对数据处理
规则是 把前后有数字的空格变",",其他的空格不变!
只可以用 正则表示式了
我用的UltraEdit,他里面的替换要使用他自己的正则表达式
可以看看他的帮助,但是原理是一样的
我先找
"[0-9] +" [0-9是表示前面是个数,后面一个空格,+是一次或者多次]
把他替换为","
但是这样有问题 ,连空格前的那个数字也替换了
我们要保留那个数字,怎么办??
用子匹配捕获
"([0-9]) +" --要用UltraEdit自己定义的"^([0-9]^) +"
替换为
"^1," --这里是UltraEdit自己的反向引用
成功了!!
当然,UltraEdit非常强大,也提供通用的正则表达式
就是大家都在用的,正确的叫法是"Unix Syntax"
在UltraEdit,有
Regular Expressions (UltraEdit Syntax):
Regular Expressions (Unix Syntax):
知道了吧
那么怎么在UltraEdit使用Unix Syntax呢??
老版本里 高级|配置|查找|UNIX形式的正则表达式
新版本里,直接在查找 替换里选择
Regular Expressions Engine:
有三种:
Perl
Unix
UltraEdit
慢慢玩吧
如果改了引擎,再按照上面的操作,什么都找不到了
要这样写了,这次不写引号了
([0-9]) +
\1,
===这个好,更通用了
再来一个例子:
也在UtralEdit里
有一个文件,N多行
"北京张肖像好老师","张肖像","zxx@itcast.com"
"南极某老师好老师","笨蛋","bendan@ddd.com"
现在要发邮件了,N多个人都要发
一个一个复制邮件地址不可能
用正则表达式揪出来:
(.+@.+\..+)
替换为
\1
.已经被定义是 元字符 所以要用真的. 要转义\.
上面的定义是不是有问题,是的
---
顺便说一下,从一堆文本里找东西,
1把要的东西找出来
2把不要的东西删除
----
上面的意思是:把邮件地址找出来,替换为邮件地址,
根本就没有上面意义
要这样写:[不加引号了]
.+"(.+@.+\..+)"
\1
OK,查找的东西就匹配有邮件地址的一整行了,
然后只是把()里的邮件保留下来
看仔细,保留下来的只是邮件,两个引号也没有了,[不在()里]
这两个引号是邮件那一列的引号!
重要重要:
更加严格,更加规范的写法是:
^.+"(.+@.+\..+)"$
\1
^表示行首,$表示行尾
写了这两个,那肯定是匹配一整行的
"北京张肖像好老师","张肖像","zxx@itcast.com"
如果不写,有可能只匹配:
好老师","张肖像","zxx@itcast.com" [如果好前面有什么特别的东西]
那么这样的话, 那个特殊的东西前面的东西就不被管辖了,仍然出现
还有一个问题:
如果我们不想发给163.net呢?怎么办??
wxjj@sina.com
hubin@sott.com
scott@oracle.net
miller@jaone.net
334@163.net
sie@163.net
dfef@ssd.com
如果有这些,把163的弄掉
先用UtralEdit 引擎
---------
*@163.net
[空白]
-------------
结果是
wxjj@sina.com
hubin@sott.com
scott@oracle.net
miller@jaone.net
dfef@ssd.com
我们不要空行,怎么办???
重要:原来在每行后面,都有\r\n
也不要去弄清楚\r\n到底是写在行开头还尾巴处,
他们就是行和尾巴,在电脑里16个字符一行,任何符号都平等
\r\n的16禁止是: 0D 0A
现在知道了那么多,再弄弄好
不要空行出现了
规范的做法是 删此行的\n and 后面的\r
也可以说:删前一行的\n 和自己的\r 还有个\n留给上行的\r配对
--------UtralEdit 引擎----
^n*@163.net^r
[空白]
---------OK---
--------Unix 引擎----
.+@163.net
[]
------------会出现空行
--------Unix 引擎----
^.+@163.net$
[]
------------还是会出现空行 奇怪了[难怪UtralEdit强大]
^.+@163.net\p [弄好了,这样!前面可无^ 但是\p前不可以$]
--------------
==把所有域名换sina.ocm
--------UtralEdit 引擎----
%^(*@^)*$
^1sina.com
---------------可以,但是如果最后一行没有打回车,他不换
所以建议最行一行都按回车,为什么EDITPLUS 按键说明文本会多一行
如果用下面的会出现什么呢?
--------UtralEdit 引擎----
%^(*@^)*
^1sina.com
-----
wxjj@sina.comsina.com
hubin@sina.comsott.com
scott@sina.comoracle.net
miller@sina.comjaone.net
334@sina.com163.net
sie@sina.com163.net
dfef@sina.comssd.com
现在知道为什么要设计$,否则都不知道哪里结束!就给了*
--------Unix 引擎----
^(.+@).+$
\1sina.com
----可以,试试不写$
^(.+@).+
\1sina.com
-----这个引擎不写倒是没有关系,但是推荐还是写为好
然后最后一个功能
把每行前都加#
--------UtralEdit 引擎----
%
#
---------OK
^r
#
--------在屁股后面加了
^n
#
-------是在前面加了,不过加完都跑一行去了
还是用%把,反正文档也说%是开始
--------Unix 引擎----
^
#
-----非常简单
★RegExp对象
★String对象中与正则表达式有关的方法
★语法参考
★实用例子
==========================================
001 regex 概述
★正则表达式及其作用
★RegExp对象
还是回到JS
在JS里有一个对象
RegExp
一条正则表达式模式对应一个RegExp对象
RegExp创建有两种方式
1显式构造函数 new RegExp("pattern"[,"flags"])
2隐式构造函数 纯文本格式 /pattern/[flags]
flag
g : 全局标志 匹配一堆时,不设置这个标志,匹配完一次就结束了
[搜索一次,替换一次]
用了这了,匹配完整个一堆字串[搜索所有,替换所有]
i : 忽略大小写标志
m : 多行标志
这个不设置,那么元字符"^" 只匹配一堆的第一个开始
"$"只匹配一堆的结束
如果设置了,"^"可以匹配\n 或者 \r [下行行首]
"$"可以匹配\n或者\r 之前 [一行结束]
注意:\是特殊符号,所有在显式构造函数里,要\\
等价的语句:
var re = new RegExp("\\d{5}");
var re = /\d{5}/;
字符有 原义 和 转义
如果要表示 原义\
在显式构造函数 四个 \\\\
在隐式构造函数 两个 \\
--------
JS里,一个RegExp就全部包含了正则表达式
JAVA里,两个类包含了
Pattern Matcher
C#里,不清楚了,看看MSDN了,好象非常多,
regexp全世界都一样,会了一种语言的,另外的语言
只要稍微看看帮助就可以上手了
--------
RegExp对象的属性
1 静态属性 所有对象共享
2 实例属性 单个实例所有
1 静态属性 所有对象共享
静态属性一般是不变,但是也可以变
比如中国人这个类有个人口数量的变量
这个变量会随着每创建一个人而改变
2 实例属性 单个实例所有
静态属性 实例属性
index global
input ignoreCase
lastIndex multiline
lastMatch source
lastParen 实例方法
leftContext compile
rightContext exec
$1...$9 test
看MSDN,这里随便说一点
index
只读
当前的模式在一堆里面的第一次匹配的文本内容的位置[0开头]
初始值-1 匹配一次改变一次
lastIndex
只读
当前的模式在一堆里面的第一次匹配的文本内容的
最后一个字符的下一个位置.[0开头 就是0开始计数]
初始值-1 匹配一次改变一次
这个属性一般用来 作为一个起始位置,什么起始位置呢?
就是还用当前模式,匹配那一堆剩余的字串
input 初始值""
返回模式现在在那个字串上作用的那个字串
lastMatch 初始值 "" 匹配一次改变一次
一个模式在一堆里可能多处匹配
这个返回最后一个匹配的字串
lastParen 初始值 "" 匹配一次改变一次
如果模式里有(),返回最后的()匹配的字串
leftContext 初始值 "" 匹配一次改变一次
模式在一堆里最后一个匹配的字串的 左边的所有字串
rightContext 初始值 "" 匹配一次改变一次
模式在一堆里最后一个匹配的字串的 右边的所有字串
$1...$9 模式里的(),模式可以写N 多()
但是JS只记得最后 9 个 但是在方法里,可以得到所有
global
ignoreCase
multiline
上面三个就flag里的三个字母 都是boolean值
source 模式的文本!
方法:
test
格式: test(str), 重要:
只是检查这个str里是不是存在匹配我模式的字串,
是不是存在,存在了几次,呵呵,
现在明白为什么有^$了,
如果存在,那么就会改变 RegExp的那些静态变量了
对于这个方法,只要有存在的 就返回 true
exec
格式: exec(str)
用我的模式去搜索str,返回搜索结果的数组
没有找到 null
找到了 数组,并也会更新 那些静态变量
找到的话,数组[0]是完整的匹配字符
1-N.. 是子匹配
这就是没有设置g 的match方法[设置了g的match方法的数组都是完全匹配的东西]
如果设置了g,从 lastIndex 搜
没有设置,整个都艘.
还有,返回的数组还用三个属性
input[一堆] index lastIndex[这两个都是描述匹配字串的]
可能会根据 lastIndex loop 再寻找吧[是的,看例子]
compile
格式:compile("pattern"[,"flags"]);
更换模式,这个方法可以优化一下!
重要说明:
如果为模式设置了g, 如果设置了g,从 lastIndex 搜
多次调用exec test 方法
由于每次搜完后lastIndex都可能变,所以多次结果可能不同
统统找出来!
如果没有设置g 忽略lastIndex,每次都是从头开始
★String对象中与正则表达式有关的方法
★语法参考
★实用例子
========================================
001 regex 概述
★正则表达式及其作用
★RegExp对象
弄个好例子吧,要不然白学了
找这样一个东西 a后一个数字b后二个数字c后三个数字
<html>
<head>
<script language="javascript">
var strSrc= "xxa1b01c001yya2b02c002zz";
var re = /a(\d)b(\d{2})c(\d{3})/gi;
var arr ,count =0;
while((arr=re.exec(strSrc))!=null)
{
displeyResult();
}
function displeyResult()
{
document.write("<p>这是用正表达式/"+re.source+"/gi对字符串<br>\""+
RegExp.input+"\"进行第"+(++count)+"次查找的结果:<br>");
document.write("RegExp.index为"+RegExp.index+"<br>");
document.write("RegExp.lastIndex为"+RegExp.lastIndex+"<br>");
document.write("RegExp.lastMatch为"+RegExp.lastMatch+"<br>");
document.write("RegExp.lastParen为"+RegExp.lastParen+"<br>");
document.write("RegExp.leftContext为"+RegExp.leftContext+"<br>");
document.write("RegExp.rightContext为"+RegExp.rightContext+"<br>");
document.write("RegExp.$1为"+RegExp.$1+"<br>");
document.write("RegExp.$2为"+RegExp.$2+"<br>");
document.write("RegExp.$3为"+RegExp.$3+"<br>");
document.write("RegExp.$4为"+RegExp.$4+"<br>");
document.write("arr.inedex为"+arr.index+"<br>");
document.write("arr.input为"+arr.input+"<br>");
document.write("arr.lastIndex为"+arr.lastIndex+"<br>");
document.write("返回数组元素的个数为"+arr.length+"<br>");
document.write("返回数组元素的内容为[");
for(var i=0;i<arr.length;i++)
{
if(i<arr.length-1)
{
document.write("\""+arr[i]+"\",");
}else
{
document.write("\""+arr[i]+"\"]</p>");
}
}
}
</script>
<body>
body!
</body>
</html>
★String对象中与正则表达式有关的方法
1 match
格式 match(re) [和exec方法交换了一下主宾关系]
如果在re里没有设置g,那返回的数组只有0完全匹配,其他子匹配
设置g, 数组里都是 完全匹配的
<html>
<head>
<script language="javascript">
var strSrc= "xxa1b01c001yya2b02c002zz";
var re = /a(\d)b(\d{2})c(\d{3})/gi;
var arr = strSrc.match(re);
document.write("返回数组元素的个数为"+arr.length+"<br>");
document.write("返回数组元素的内容为[");
for(var i=0;i<arr.length;i++)
{
if(i<arr.length-1)
{
document.write("\""+arr[i]+"\",");
}else
{
document.write("\""+arr[i]+"\"]</p>");
}
}
</script>
<body>
body!
</body>
</html>
------------
返回数组元素的个数为2
返回数组元素的内容为["a1b01c001","a2b02c002"]
-------------
重要,不设置g
返回数组元素的个数为4
返回数组元素的内容为["a1b01c001","1","01","001"]
2
search方法
格式search(re) 返回第一个匹配的字串在一堆里的位置!
3
replace
格式replace(re,replaceTxt) 返回替换后的串或者一堆
先用re去找匹配的内容,再把找到的换掉
这里的re部分也可以是普通字串,那就要精确搜索了
replaceTxt这里也有考究了
$$ $原义
$& 整个模式匹配的内容
$` 位于$& 前面的内容
$' 位于$& 后面的内容
$n 第n个()里的内容 [非常有用]
$nn 一样的,如果没有,就是输出$nn
一个例子
把a12b34c56这里的连续两个数字 调个个,
a12b34c56 has been converted into a21b43c65
注意:这里的RE通常要设置g才可以替换所有的
4
split方法
格式:split(separator[,limit])
返回一个数组
separator 可以是re或者多个字符 [不会作为数组的一部分返回]
limit[要返回多少个,有时候不是要全部返回的]
=====================回顾============
重要:
re的exec 有g 下一次从lastIndex 搜
while((arr=re.exec(strSrc))!=null)
{
displeyResult();
}
无g 老是从头开始
不管有g无g,回来的数组都只有第一个0完全匹配
str的match match(re)
如果在re里没有设置g,那返回的数组只有0完全匹配,其他子匹配
设置g, 数组里都是 完全匹配的
=================================
★语法参考
★实用例子
=====================
001 regex 概述
★正则表达式及其作用
★RegExp对象
★语法参考
要强大的使用RE,必须了解元字符
写RE,就是拼凑元字符
★限定符[6个 3+3]
用来指定前面的 字符 或者 组合项 连续出现多少次.
{n} : 前面的 字符 或者 组合项 必须要连续出现n次!
o{2} 不匹配Bob里的o ,但是匹配food 也匹配boooook中的任意两个o
{n,} : 前面的 字符 或者 组合项 至少要连续出现n次!
o{2,} 不匹配Bob里的o ,匹配boooook中的 所有的o
{n,m} : 前面的 字符 或者 组合项 连续出现[n,m] 两边都包含的
o{1,3} 匹配Bob里的o ,匹配book中的两个o 重要重要也匹配foooood里的连续三个o
其实刚刚的重要根本没有必要了,到了现在,应该理解了
对于电脑,一篇小说也是一串连续的东西,不要以为单词长了,太长了就不匹配了
那要匹配一本小说,有谁会把一个模式写成一本小说去匹配啊!
+ 等效 {1,} 必须出现一次或者多次
zo+ 匹配 zo zoo
* 等效 {0,} zero or more !
zo* 匹配 z zoo
? {0,1}
zo? 匹配 z zo 重要重要[都不知道该不该说 ] 也匹配 zoo
呵呵,匹配zoo里的zo部分,不匹配整个 zoo
上面有问题来了,
o{1,3} 可以匹配1-3个o,那么到底匹配book中的几个o呢??
贪兰匹配和非贪斓匹配
贪兰匹配[默认的]
要把zoom里的 zo? 换 r 结果是rom 不是room
要把zoom里的 zo* 换 r 结果是 rm 不是rom 也不是room
非贪斓匹配
把? 紧随任何其他 限定符(* + ? {n} {n,} {n,m}
匹配模式就变 非贪斓匹配
fooood里, fo+? 只匹配 fo 部分 [不贪]
fo+ 就匹配了 foooo 了[贪了]
★选择匹配符[一个 |]
用来匹配 | 两边的任意一个
注意 | 两边的的表达式尽可能大哦
比如:
chapter|section 1 只匹配 chapter 或者 section 1
不是 chapter 1 或者section 1
如果要匹配 chapter 1 或者section 1
可以这样写
(chapter|section) 1
★分组组合和反向引用符
这两个是一对
()分组组合
\n反向引用符,用来获得前面 捕获到的内容
(pattern) 捕获到的东西存在缓冲区,最多99个,
可以被反向引用,也可以在编程语言里检索到
如果要匹配 原义() 就要用 \( \)
\n or \nn
这个最最强大,最最常用的功能,就是匹配 相同项目的能力
例如,要匹配连续5个字符 \d{5}
但是,要匹配连续5个 相同的 数字呢 就要用反向了
(\d)\1{4}
=========找想同的单词出现=========
<html>
<head>
<script language="javascript">
var strSrc = "Is is the cost of of gasonline going up up?";
var re = /\b([a-z]+) \1\b/gi;
var arr = strSrc.match(re);
document.write("返回数组元素的个数为"+arr.length+"<br>");
document.write("返回数组元素的内容为[");
for(var i=0;i<arr.length;i++)
{
if(i<arr.length-1)
{
document.write("\""+arr[i]+"\",");
}else
{
document.write("\""+arr[i]+"\"]</p>");
}
}
</script>
<body>
返回数组元素的个数为3
返回数组元素的内容为["Is is","of of","up up"]
</body>
</html>
===============================
(?:pattern)
有时候必须要用(),但是又不想存到缓存区就用这个好了
情况有:
不可以将 industry|industries 简单写成 industr(y|ise)
会影响 缓存区的位置的,你这个()里放的都是些没有实际意义的东西
就可以写成 industr(?:y|ise)
(?=pattern)[这个不说情况打死也不知道再说什么]
正 向 预测先行 匹配
就是说 在 一堆里的东西附近一定要有这个,但是这个不放结果里,
更不放缓存里
比如在一大堆里有 window 2000 ,window NT ,window 2003
出现了N多次N多次,我现在只想对出现在2000 或者NT前的window操作怎么办?
就用这个 windows (?=NT|2000)
重要:匹配的结果 只是 windows 部分哦
如果把=变: 就匹配NT 或者 2000都进来了,虽然缓存里是不放的!!
--------思考---
window (?=NT|2000) series ,会不会匹配 window NT series
这要想死人的,别想了
记得 这个东西要么写在最前,要么写在最后
---------------
(?!pattern)反 向 预测先行 匹配
说明在一堆的相应处,不可以出现模式里的东西
和上面的基本类似!
window (?!NT|2000)
一大堆里有 window 2000 ,window NT ,window 2003
这下子只匹配 最后一个window
★特殊字符
RE里可以用(\)来表示 非打印字符 和 原义字符
\xn 匹配ASCII码等于n的字符n必须是两位16禁止数
\x41表示 A ,注意 \x041 表示 \x04 后面来一个1
这种方式一看就可以知道,可以匹配所有的字符,但是谁能记得呢???
\n 前面有() 当 反向引用 没有么 就只能0-7 ,ASCII码了
\nm 前面有() ,前小于n个, \n 当反向用 m普通字符
大于n个 nm一起上,当反响用
没有,都是一位的8禁止数, ASCII码了
\nml n小于3 最多(255)这些都是给高高手用的
ml8禁止数
ASCII码
\un unicode码了 n 四位16禁止数
\cx 匹配x 代表的控制字符
\cM 匹配 control + M 就是回车符了
x必须是字母,否则c就是c x就是x了
-----------
重要:在ASCII码里 16禁止的 00 -1F 之间的数字所表现的字符
是不可见的,也打印不出来
这些字符叫 控制字符
他们在一些特殊的场合使用
每个控制字符都有一个英文名称来表示意义和作用
在一些终端上,就是用control + M 来表示回车的,它没有回车键
可以按.
control + M 回车键
control + H 退各键
control + C 不知道什么键,反正有用
cmd里试吧 cmd里还有一个 control + i
看看吧
我们也可以用UtralEdit来看控制字符
view | views/list | ASCII table
-----------
\t 匹配制表符 等效于 \x09 \cI
\n 匹配换行符 等效于 \x0a \cJ
\v 垂直制表符 等效于 \x0b \cK
\f 匹配换页符 等效于 \x0c \cL
\r 匹配回车符 等效于 \x0d \cM
★字符匹配符
1[]
匹配[]里多个字符的任意一个
如果模式里有 原义] ,必须放第一位,紧挨[后面,这样就认得,
[]里面的\仍然做 转义 要用原义 \\
但是不知道 [ 原义怎么弄
2[^]
第一个是^ 就是排除,和上面对应的学
注意 ^不排第一 ,就是原义
3[a-z]
范围来了
注意:[]里要用 原义- 可\- [a\-z] [只有三个哦]
也可以把-放最前或者最后 [-a-z] [a-z-] [27个哦]
4[^a-z]
不在范围里的
\d 数字 等效 [0-9]
\D 数字 等效 [^0-9]
\s 等效[ \t\n\v\f\r] 任何空格 这里TMD是6个,有个空格看不见,呵呵
\S 等效[^ \t\n\v\f\r]
\w 等效 [A-Za-z0-9_] 26+26+10+1
\W 等效 [^A-Za-z0-9_]
. 匹配 所有的 除了 \n
(.)\1
匹配除 \n 外的两个连续的相同的字符
[\s\S] [\d\D] [\w\W]
这三个什么字符都匹配了
如果要匹配 原义. 要\.
看一个例子, 结巴翻译
把下面的话理顺一下:
"I...I...want...eat...eat...rice!"
"我....我要...吃...吃肥肠面!"
变"我要吃肥肠面!"
<html>
<head>
<script language="javascript">
var strSrc = "我....我要...吃...吃肥肠面!";
var strTgt= strSrc.replace(/\./g,"").replace(/(.)\1/g,"$1");
document.write(strTgt);
</script>
<body>
body!
</body>
</html>
==============这个我自己弄了半夜========
<html>
<head>
<script language="javascript">
var strSrc = "I...I...want...eat...eat...rice!";
var strTgt= strSrc.replace(/(\.)+/g," ").replace(/(\w+) \1/g,"$1");
//var strTgt= strSrc.replace(/\./g," ").replace(/e/g,"E");
document.write(strTgt);
</script>
<body>
</body>
</html>
==========I want eat rice!======================
★定位符
用于规定符合模式的字串出现的位置
这对验证非常有用
^ 匹配字串的开始位置 注意^必须写在模式的最前才有这个用
例子:
^o与ok 里的o匹配 hello里的o不匹配!
如果设置了multiline属性[这个还是要好好推敲,一般输入验证,也就那么一段]
^还会与行首匹配 \n \r之后的位置匹配
$ 匹配字串的结尾位置 注意$必须写在模式的最后才有这个用
如果设置了multiline属性
\n \r之前的位置匹配
\b
两边不全是\w
\B
非边界,应该好理解的
例子:
er\B 匹配 verb 的er 不匹配never 的 er
定位符实用例子
=============================
在对大段大段的文本操作的时候,
写模式要小心,
如果要匹配某一个单词
一定要/\bwin\b/g
边界一定要,英文单词单词里有单词很常见
-------------
再来一个例子,搜索义每而
可以这样
/[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+/
这可以搜索 邮箱地址了,但是搜不到我的,先不管
要注意的是这种不可以用的网页表单里
因为像这样
@.it33@it222.com.?
的不合法字串里包含有 合法的字串
用re.test()去验证,test不会关心合法字串出现的位置
所以,定位符还是要派上用场的
规范的写法/^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/
重要重要,但是你要在一堆里搜索,又不可以这样写了
哎,真够烦!
-----------------再来一个定位符例子
要在每行前加一个# ,注释每行,可以这样:
<html>
<head>
<script language="javascript">
var strTxt = "first line\n" +
"second line\n" +
"third line\n" +
"fourth line\n" +
"fifth line\n";
//document.write(strTxt.replace(/^/mg,"#"));
alert(strTxt.replace(/^/mg,"#"));
</script>
<body>
</body>
</html>
一定要加 flag m g!
=============================
★原义字符
一些字符已经定义为 元字符 了,如果要用他们的原义
必须用 \ 来转义
需要转义的字符有:
$ ( ) * + . [ ] ? \ / ^ { } |
对于/,由于写模式时需要用到它
所以要用/的原义,也必须转义 \/
==========
看一下优先级别
()最高
(ab)* ab组合后再和*组合
*
ab* b和*先组合后再和a组合
字符
没有什么例子
| 最低
a|bc bc组合后,再和a组合
==========
★实用例子
匹配空行[所有的空行(真空行,假空行都匹配)都匹配]
/^\s*$/
匹配假空行[就是说,直接换行的真空行不算,空行里有 空格,制表符等的空行]
^[\\s&&[^\\r]&&[^\\n]]\\s*\\n$ [查找脏空行的]
这个里有怎么使用 && 的.
就是说,开始是一个空白,但是这个空白不可以是直接就换行
匹配HTML标记
/<(\S+)(\s[^>]*)?>[\s\S]*<\/\1s*>/
匹配email
/[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+/
匹配相同的相邻的单词[小写情况]
/\b([a-z]+) \1\b/
匹配IP
/^\d{1,2}|1\d\d|2[0-4]\d|25[0-5](\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])){3}$/
===========
重要重要,程序做判断
返回true一定要放最后,把不合法的都放前面,一有不合法的,直接return掉!
实用程序举例一
校验ip地址是否合法程序
第一种:
function js_verify(addr)
{
var part_addr=addr.split(".");
if(part_addr.length!=4)
{
return false;
}
else
{
var part;
for(part in part_addr)
{
if(isNumeric(part_addr[part]))
{
if(parseInt(part_addr[part])<0||parseInt(part_addr[part])>255)
{
return false;
}
}
else
{
return false;
}
}
}
return true;
}
function isNumeric(str)
{
if(str.length==0)
{
return false;
}
for(var i=0;i<str.length;i++)
{
if(str.charAt(i)<"0"||str.charAt(i)>"9")
{
return false;
}
}
return true;
}
第二种方法:
function jsreg_verify(addr)
{
var reg=/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/;
if(reg.exec(addr)!=null)
{
//下面直接用字符串与数值比较,字符串将先转换成数值
if(RegExp.$1<0||RegExp.$1>255) return false;
if(RegExp.$2<0||RegExp.$2>255) return false;
if(RegExp.$3<0||RegExp.$3>255) return false;
if(RegExp.$4<0||RegExp.$4>255) return false;
}
else
{
return false;
}
return true;
}
第三种方法:
/*reg_verify - 完全正则表达式来判断一个字符串是否是合法的ip地址,如果是则返回true,否则返回false.*/
function reg_verify(addr)
{
var reg=/^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])(\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])){3}$/;
if(addr.match(reg))
{
return true;
}
else
{
return false;
}
}
用于检验的HTML代码:
<p>输入要检验的ip地址:<input type=text name=txtIp value="255.222.33.111"><br>
<input type=button name=btn1 value="测试JavaScript验证" onclick="alert(js_verify(txtIp.value))"><br>
<input type=button name=btn1 value="测试JavaScript和正则表达式验证" onclick="alert(jsreg_verify(txtIp.value))"><br>
<input type=button name=btn1 value="测试正则表达式验证" onclick="alert(reg_verify(txtIp.value))"><br></p>
============copy it into IE=====
<html>
<head>
<title>ss</title>
<head>
<script language="javascript">
function js_verify(addr)
{
var part_addr=addr.split(".");
if(part_addr.length!=4)
{
return false;
}
else
{
var part;
for(part in part_addr)
{
if(isNumeric(part_addr[part]))
{
if(parseInt(part_addr[part])<0||parseInt(part_addr[part])>255)
{
return false;
}
}
else
{
return false;
}
}
}
return true;
}
function isNumeric(str)
{
if(str.length==0)
{
return false;
}
for(var i=0;i<str.length;i++)
{
if(str.charAt(i)<"0"||str.charAt(i)>"9")
{
return false;
}
}
return true;
}
function jsreg_verify(addr)
{
var reg=/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/;
if(reg.exec(addr)!=null)
{
//下面直接用字符串与数值比较,字符串将先转换成数值
if(RegExp.$1<0||RegExp.$1>255) return false;
if(RegExp.$2<0||RegExp.$2>255) return false;
if(RegExp.$3<0||RegExp.$3>255) return false;
if(RegExp.$4<0||RegExp.$4>255) return false;
}
else
{
return false;
}
return true;
}
function reg_verify(addr)
{
var reg=/^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])(\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])){3}$/;
if(addr.match(reg))
{
return true;
}
else
{
return false;
}
}
</script>
</head>
<body>
用于检验的HTML代码:
<p>输入要检验的ip地址:<input type=text name=txtIp value="255.222.33.111"><br>
<input type=button name=btn1 value="测试JavaScript验证" onclick="alert(js_verify(txtIp.value))"><br>
<input type=button name=btn1 value="测试JavaScript和正则表达式验证" onclick="alert(jsreg_verify(txtIp.value))"><br>
<input type=button name=btn1 value="测试正则表达式验证" onclick="alert(reg_verify(txtIp.value))"><br></p>
</body>
</html>
======================over
实用程序举例二
---从统一资源定位符(URL)中提取各组件信息
问题分析:
当浏览器地址栏中输入http://www.it315.org/book/welcome.html或http://192.168.0.1:8080/index.html等URL地址时,浏览器内部将会作出怎样的具体处理呢?
示例程序代码:
<script>
var reg=/(\w+):\/\/([^/:]+)(?::(\d*))?([^# ]*)/;
var arr1="http://www.it315.org:8080/index.html".match(reg);
var arr2="http://www.it315.org/book/welcome.html#mark1".match(reg);
var str="协议,主机名,端口号,资源路径\n";
str+=arr1[1]+", "+arr1[2]+", "+arr1[3]+", "+arr1[4]+"\n";
str+=RegExp.$1+", "+RegExp.$2+", "+RegExp.$3+", "+RegExp.$4+"\n";
alert(str);
</script>
实用程序举例三
---创建能对多种常用格式进行验证的函数
<script>
var patterns=new Object();
patterns.ip=/^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])(\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])){3}$/;
patterns.email=/^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/;
patterns.date=/^\d{4}-(0?[1-9]|1[0-2])-(0?[1-9]|[1-2]\d|3[0-1])$/;//匹配日期格式2008-01-31,但不匹配2008-13-00
patterns.time=new RegExp("^([0-1]\\d|2[0-3]):[0-5]\\d:[0-5]\\d$");//匹配时间格式00:15:39,但不匹配24:60:00
function verify(str,pat)
{
thePat=patterns[pat];
if(thePat.test(str))
{
return true;
}
else
{
return false;
}
}
alert(verify("00:00:11","time")+","+verify("it315@it315.org","email")+","+verify("192.168.1.1","ip")+","+verify("2003-00-31","date"));
</script>
===================================
★正则表达式及其作用
老的: ? >> once * >> zero or more
正则表达式类似,强大了点,灵活了点
正则表达式[翻译的不好]
regular expression
英文的意思是:符合某种规则的表达式
可以把正则表达式当一种语言[文本模式]
去匹配文本串,或者说文本串来匹配模式
正则表达式由一些元字符组成,
这些一组成,那么这个正则表达式就不是文本内容了,
而是一种文本模式
元字符(metacharacter)特殊字符
比如你要在一堆文字里查找这东西
要么5个数字 要么5个数字后加
连字符再加4个数字 共十个
可以用
\d{5}(-\d{4})?
正则表达式里的 ? 表示 once or not at all
重要重要 仅仅表示 紧考在 ? 前面 的元素项哦
所以我用()!!
-----------------
再说一个例子:
关于 ? 的
abc? 匹配 ab 或者 abc
a(bc)? 匹配 a 或者 abc
-----------------
重要:刚刚看见() 的作用了
() 还有一个更厉害的作用:
他 括起来的东西也叫一个 "子匹配"
除了可以得到 整个 正则表达式的匹配结果外,
还可以单独得到每个 子匹配 所匹配的结果
就是说可以用() 把一个长的 正则表达式 分为多个子表达式
多个子表达式匹配的内容按照他们在正则表达式 左到右 出现
的顺序存储在缓存区里,这叫"捕获"
这样说肯定不懂,说个需求
我现在要匹配555香烟,三个数字要一样
\d{3}这样的话123 456 都出来了,不要!!
---
上面说完 捕获, 捕获好了后可以在整个表达式中位于
这个括号后的地方"反向引用"
第一个() 用 \1 表示
第二个() 用 \2 表示
...
所以要匹配2个相同的连续数字字符的正则表达式为
(\d)\1
刚刚的三五香烟
(\d)\1{2} [就是说\1还得出来2次哦,必须2次哦]
要匹配这样的数字 1221 3553 7887 个位千位一样 十位百位一样
(\d)(\d)\2\1
=============
来看看作用:
1
测试字串是不是匹配某个模式,看看输入的数据是不是有效
2
将一堆文本满足某一表达模式的文本内容替换或者删除[既替换为空即可]
比如在一堆文本中 把19XX的内容换成20XX [XX不变]
不可以简单的把19换20哦,否则1919 要变2020 ,而需求是1919变2019
如果是那么简单 word就可以解决问题了,呵呵
3
一堆里 搜索 某一类特征的文本内容
精确搜索:搜索一个具体的文本 .例如用 word 软件[必须提供精确内容哦]
而正则搜索: 可以搜索出某一类的文本[提供模式就可以了]
--------
顺便说一下为什么要用TXT CSV
TXT存在是因为他太通用了,什么软件都可以打开查看
CSV是因为有时候TXT的一个整体里有空格什么的,很难分,所以用","了
--------
说一个例子
在一文本里有上亿行数据[其中一行是这样的]
0.0.0.0 0.255.255.255 IANA 未知地区
现在要把这上亿条记录放DB里,三列,一二列是IP 第三列是说明
现在没有DB不认识,DB说我要根据什么分呢?空格?说明里也有空格啊
所以先要对数据处理
规则是 把前后有数字的空格变",",其他的空格不变!
只可以用 正则表示式了
我用的UltraEdit,他里面的替换要使用他自己的正则表达式
可以看看他的帮助,但是原理是一样的
我先找
"[0-9] +" [0-9是表示前面是个数,后面一个空格,+是一次或者多次]
把他替换为","
但是这样有问题 ,连空格前的那个数字也替换了
我们要保留那个数字,怎么办??
用子匹配捕获
"([0-9]) +" --要用UltraEdit自己定义的"^([0-9]^) +"
替换为
"^1," --这里是UltraEdit自己的反向引用
成功了!!
当然,UltraEdit非常强大,也提供通用的正则表达式
就是大家都在用的,正确的叫法是"Unix Syntax"
在UltraEdit,有
Regular Expressions (UltraEdit Syntax):
Regular Expressions (Unix Syntax):
知道了吧
那么怎么在UltraEdit使用Unix Syntax呢??
老版本里 高级|配置|查找|UNIX形式的正则表达式
新版本里,直接在查找 替换里选择
Regular Expressions Engine:
有三种:
Perl
Unix
UltraEdit
慢慢玩吧
如果改了引擎,再按照上面的操作,什么都找不到了
要这样写了,这次不写引号了
([0-9]) +
\1,
===这个好,更通用了
再来一个例子:
也在UtralEdit里
有一个文件,N多行
"北京张肖像好老师","张肖像","zxx@itcast.com"
"南极某老师好老师","笨蛋","bendan@ddd.com"
现在要发邮件了,N多个人都要发
一个一个复制邮件地址不可能
用正则表达式揪出来:
(.+@.+\..+)
替换为
\1
.已经被定义是 元字符 所以要用真的. 要转义\.
上面的定义是不是有问题,是的
---
顺便说一下,从一堆文本里找东西,
1把要的东西找出来
2把不要的东西删除
----
上面的意思是:把邮件地址找出来,替换为邮件地址,
根本就没有上面意义
要这样写:[不加引号了]
.+"(.+@.+\..+)"
\1
OK,查找的东西就匹配有邮件地址的一整行了,
然后只是把()里的邮件保留下来
看仔细,保留下来的只是邮件,两个引号也没有了,[不在()里]
这两个引号是邮件那一列的引号!
重要重要:
更加严格,更加规范的写法是:
^.+"(.+@.+\..+)"$
\1
^表示行首,$表示行尾
写了这两个,那肯定是匹配一整行的
"北京张肖像好老师","张肖像","zxx@itcast.com"
如果不写,有可能只匹配:
好老师","张肖像","zxx@itcast.com" [如果好前面有什么特别的东西]
那么这样的话, 那个特殊的东西前面的东西就不被管辖了,仍然出现
还有一个问题:
如果我们不想发给163.net呢?怎么办??
wxjj@sina.com
hubin@sott.com
scott@oracle.net
miller@jaone.net
334@163.net
sie@163.net
dfef@ssd.com
如果有这些,把163的弄掉
先用UtralEdit 引擎
---------
*@163.net
[空白]
-------------
结果是
wxjj@sina.com
hubin@sott.com
scott@oracle.net
miller@jaone.net
dfef@ssd.com
我们不要空行,怎么办???
重要:原来在每行后面,都有\r\n
也不要去弄清楚\r\n到底是写在行开头还尾巴处,
他们就是行和尾巴,在电脑里16个字符一行,任何符号都平等
\r\n的16禁止是: 0D 0A
现在知道了那么多,再弄弄好
不要空行出现了
规范的做法是 删此行的\n and 后面的\r
也可以说:删前一行的\n 和自己的\r 还有个\n留给上行的\r配对
--------UtralEdit 引擎----
^n*@163.net^r
[空白]
---------OK---
--------Unix 引擎----
.+@163.net
[]
------------会出现空行
--------Unix 引擎----
^.+@163.net$
[]
------------还是会出现空行 奇怪了[难怪UtralEdit强大]
^.+@163.net\p [弄好了,这样!前面可无^ 但是\p前不可以$]
--------------
==把所有域名换sina.ocm
--------UtralEdit 引擎----
%^(*@^)*$
^1sina.com
---------------可以,但是如果最后一行没有打回车,他不换
所以建议最行一行都按回车,为什么EDITPLUS 按键说明文本会多一行
如果用下面的会出现什么呢?
--------UtralEdit 引擎----
%^(*@^)*
^1sina.com
-----
wxjj@sina.comsina.com
hubin@sina.comsott.com
scott@sina.comoracle.net
miller@sina.comjaone.net
334@sina.com163.net
sie@sina.com163.net
dfef@sina.comssd.com
现在知道为什么要设计$,否则都不知道哪里结束!就给了*
--------Unix 引擎----
^(.+@).+$
\1sina.com
----可以,试试不写$
^(.+@).+
\1sina.com
-----这个引擎不写倒是没有关系,但是推荐还是写为好
然后最后一个功能
把每行前都加#
--------UtralEdit 引擎----
%
#
---------OK
^r
#
--------在屁股后面加了
^n
#
-------是在前面加了,不过加完都跑一行去了
还是用%把,反正文档也说%是开始
--------Unix 引擎----
^
#
-----非常简单
★RegExp对象
★String对象中与正则表达式有关的方法
★语法参考
★实用例子
==========================================
001 regex 概述
★正则表达式及其作用
★RegExp对象
还是回到JS
在JS里有一个对象
RegExp
一条正则表达式模式对应一个RegExp对象
RegExp创建有两种方式
1显式构造函数 new RegExp("pattern"[,"flags"])
2隐式构造函数 纯文本格式 /pattern/[flags]
flag
g : 全局标志 匹配一堆时,不设置这个标志,匹配完一次就结束了
[搜索一次,替换一次]
用了这了,匹配完整个一堆字串[搜索所有,替换所有]
i : 忽略大小写标志
m : 多行标志
这个不设置,那么元字符"^" 只匹配一堆的第一个开始
"$"只匹配一堆的结束
如果设置了,"^"可以匹配\n 或者 \r [下行行首]
"$"可以匹配\n或者\r 之前 [一行结束]
注意:\是特殊符号,所有在显式构造函数里,要\\
等价的语句:
var re = new RegExp("\\d{5}");
var re = /\d{5}/;
字符有 原义 和 转义
如果要表示 原义\
在显式构造函数 四个 \\\\
在隐式构造函数 两个 \\
--------
JS里,一个RegExp就全部包含了正则表达式
JAVA里,两个类包含了
Pattern Matcher
C#里,不清楚了,看看MSDN了,好象非常多,
regexp全世界都一样,会了一种语言的,另外的语言
只要稍微看看帮助就可以上手了
--------
RegExp对象的属性
1 静态属性 所有对象共享
2 实例属性 单个实例所有
1 静态属性 所有对象共享
静态属性一般是不变,但是也可以变
比如中国人这个类有个人口数量的变量
这个变量会随着每创建一个人而改变
2 实例属性 单个实例所有
静态属性 实例属性
index global
input ignoreCase
lastIndex multiline
lastMatch source
lastParen 实例方法
leftContext compile
rightContext exec
$1...$9 test
看MSDN,这里随便说一点
index
只读
当前的模式在一堆里面的第一次匹配的文本内容的位置[0开头]
初始值-1 匹配一次改变一次
lastIndex
只读
当前的模式在一堆里面的第一次匹配的文本内容的
最后一个字符的下一个位置.[0开头 就是0开始计数]
初始值-1 匹配一次改变一次
这个属性一般用来 作为一个起始位置,什么起始位置呢?
就是还用当前模式,匹配那一堆剩余的字串
input 初始值""
返回模式现在在那个字串上作用的那个字串
lastMatch 初始值 "" 匹配一次改变一次
一个模式在一堆里可能多处匹配
这个返回最后一个匹配的字串
lastParen 初始值 "" 匹配一次改变一次
如果模式里有(),返回最后的()匹配的字串
leftContext 初始值 "" 匹配一次改变一次
模式在一堆里最后一个匹配的字串的 左边的所有字串
rightContext 初始值 "" 匹配一次改变一次
模式在一堆里最后一个匹配的字串的 右边的所有字串
$1...$9 模式里的(),模式可以写N 多()
但是JS只记得最后 9 个 但是在方法里,可以得到所有
global
ignoreCase
multiline
上面三个就flag里的三个字母 都是boolean值
source 模式的文本!
方法:
test
格式: test(str), 重要:
只是检查这个str里是不是存在匹配我模式的字串,
是不是存在,存在了几次,呵呵,
现在明白为什么有^$了,
如果存在,那么就会改变 RegExp的那些静态变量了
对于这个方法,只要有存在的 就返回 true
exec
格式: exec(str)
用我的模式去搜索str,返回搜索结果的数组
没有找到 null
找到了 数组,并也会更新 那些静态变量
找到的话,数组[0]是完整的匹配字符
1-N.. 是子匹配
这就是没有设置g 的match方法[设置了g的match方法的数组都是完全匹配的东西]
如果设置了g,从 lastIndex 搜
没有设置,整个都艘.
还有,返回的数组还用三个属性
input[一堆] index lastIndex[这两个都是描述匹配字串的]
可能会根据 lastIndex loop 再寻找吧[是的,看例子]
compile
格式:compile("pattern"[,"flags"]);
更换模式,这个方法可以优化一下!
重要说明:
如果为模式设置了g, 如果设置了g,从 lastIndex 搜
多次调用exec test 方法
由于每次搜完后lastIndex都可能变,所以多次结果可能不同
统统找出来!
如果没有设置g 忽略lastIndex,每次都是从头开始
★String对象中与正则表达式有关的方法
★语法参考
★实用例子
========================================
001 regex 概述
★正则表达式及其作用
★RegExp对象
弄个好例子吧,要不然白学了
找这样一个东西 a后一个数字b后二个数字c后三个数字
<html>
<head>
<script language="javascript">
var strSrc= "xxa1b01c001yya2b02c002zz";
var re = /a(\d)b(\d{2})c(\d{3})/gi;
var arr ,count =0;
while((arr=re.exec(strSrc))!=null)
{
displeyResult();
}
function displeyResult()
{
document.write("<p>这是用正表达式/"+re.source+"/gi对字符串<br>\""+
RegExp.input+"\"进行第"+(++count)+"次查找的结果:<br>");
document.write("RegExp.index为"+RegExp.index+"<br>");
document.write("RegExp.lastIndex为"+RegExp.lastIndex+"<br>");
document.write("RegExp.lastMatch为"+RegExp.lastMatch+"<br>");
document.write("RegExp.lastParen为"+RegExp.lastParen+"<br>");
document.write("RegExp.leftContext为"+RegExp.leftContext+"<br>");
document.write("RegExp.rightContext为"+RegExp.rightContext+"<br>");
document.write("RegExp.$1为"+RegExp.$1+"<br>");
document.write("RegExp.$2为"+RegExp.$2+"<br>");
document.write("RegExp.$3为"+RegExp.$3+"<br>");
document.write("RegExp.$4为"+RegExp.$4+"<br>");
document.write("arr.inedex为"+arr.index+"<br>");
document.write("arr.input为"+arr.input+"<br>");
document.write("arr.lastIndex为"+arr.lastIndex+"<br>");
document.write("返回数组元素的个数为"+arr.length+"<br>");
document.write("返回数组元素的内容为[");
for(var i=0;i<arr.length;i++)
{
if(i<arr.length-1)
{
document.write("\""+arr[i]+"\",");
}else
{
document.write("\""+arr[i]+"\"]</p>");
}
}
}
</script>
<body>
body!
</body>
</html>
★String对象中与正则表达式有关的方法
1 match
格式 match(re) [和exec方法交换了一下主宾关系]
如果在re里没有设置g,那返回的数组只有0完全匹配,其他子匹配
设置g, 数组里都是 完全匹配的
<html>
<head>
<script language="javascript">
var strSrc= "xxa1b01c001yya2b02c002zz";
var re = /a(\d)b(\d{2})c(\d{3})/gi;
var arr = strSrc.match(re);
document.write("返回数组元素的个数为"+arr.length+"<br>");
document.write("返回数组元素的内容为[");
for(var i=0;i<arr.length;i++)
{
if(i<arr.length-1)
{
document.write("\""+arr[i]+"\",");
}else
{
document.write("\""+arr[i]+"\"]</p>");
}
}
</script>
<body>
body!
</body>
</html>
------------
返回数组元素的个数为2
返回数组元素的内容为["a1b01c001","a2b02c002"]
-------------
重要,不设置g
返回数组元素的个数为4
返回数组元素的内容为["a1b01c001","1","01","001"]
2
search方法
格式search(re) 返回第一个匹配的字串在一堆里的位置!
3
replace
格式replace(re,replaceTxt) 返回替换后的串或者一堆
先用re去找匹配的内容,再把找到的换掉
这里的re部分也可以是普通字串,那就要精确搜索了
replaceTxt这里也有考究了
$$ $原义
$& 整个模式匹配的内容
$` 位于$& 前面的内容
$' 位于$& 后面的内容
$n 第n个()里的内容 [非常有用]
$nn 一样的,如果没有,就是输出$nn
一个例子
把a12b34c56这里的连续两个数字 调个个,
a12b34c56 has been converted into a21b43c65
注意:这里的RE通常要设置g才可以替换所有的
4
split方法
格式:split(separator[,limit])
返回一个数组
separator 可以是re或者多个字符 [不会作为数组的一部分返回]
limit[要返回多少个,有时候不是要全部返回的]
=====================回顾============
重要:
re的exec 有g 下一次从lastIndex 搜
while((arr=re.exec(strSrc))!=null)
{
displeyResult();
}
无g 老是从头开始
不管有g无g,回来的数组都只有第一个0完全匹配
str的match match(re)
如果在re里没有设置g,那返回的数组只有0完全匹配,其他子匹配
设置g, 数组里都是 完全匹配的
=================================
★语法参考
★实用例子
=====================
001 regex 概述
★正则表达式及其作用
★RegExp对象
★语法参考
要强大的使用RE,必须了解元字符
写RE,就是拼凑元字符
★限定符[6个 3+3]
用来指定前面的 字符 或者 组合项 连续出现多少次.
{n} : 前面的 字符 或者 组合项 必须要连续出现n次!
o{2} 不匹配Bob里的o ,但是匹配food 也匹配boooook中的任意两个o
{n,} : 前面的 字符 或者 组合项 至少要连续出现n次!
o{2,} 不匹配Bob里的o ,匹配boooook中的 所有的o
{n,m} : 前面的 字符 或者 组合项 连续出现[n,m] 两边都包含的
o{1,3} 匹配Bob里的o ,匹配book中的两个o 重要重要也匹配foooood里的连续三个o
其实刚刚的重要根本没有必要了,到了现在,应该理解了
对于电脑,一篇小说也是一串连续的东西,不要以为单词长了,太长了就不匹配了
那要匹配一本小说,有谁会把一个模式写成一本小说去匹配啊!
+ 等效 {1,} 必须出现一次或者多次
zo+ 匹配 zo zoo
* 等效 {0,} zero or more !
zo* 匹配 z zoo
? {0,1}
zo? 匹配 z zo 重要重要[都不知道该不该说 ] 也匹配 zoo
呵呵,匹配zoo里的zo部分,不匹配整个 zoo
上面有问题来了,
o{1,3} 可以匹配1-3个o,那么到底匹配book中的几个o呢??
贪兰匹配和非贪斓匹配
贪兰匹配[默认的]
要把zoom里的 zo? 换 r 结果是rom 不是room
要把zoom里的 zo* 换 r 结果是 rm 不是rom 也不是room
非贪斓匹配
把? 紧随任何其他 限定符(* + ? {n} {n,} {n,m}
匹配模式就变 非贪斓匹配
fooood里, fo+? 只匹配 fo 部分 [不贪]
fo+ 就匹配了 foooo 了[贪了]
★选择匹配符[一个 |]
用来匹配 | 两边的任意一个
注意 | 两边的的表达式尽可能大哦
比如:
chapter|section 1 只匹配 chapter 或者 section 1
不是 chapter 1 或者section 1
如果要匹配 chapter 1 或者section 1
可以这样写
(chapter|section) 1
★分组组合和反向引用符
这两个是一对
()分组组合
\n反向引用符,用来获得前面 捕获到的内容
(pattern) 捕获到的东西存在缓冲区,最多99个,
可以被反向引用,也可以在编程语言里检索到
如果要匹配 原义() 就要用 \( \)
\n or \nn
这个最最强大,最最常用的功能,就是匹配 相同项目的能力
例如,要匹配连续5个字符 \d{5}
但是,要匹配连续5个 相同的 数字呢 就要用反向了
(\d)\1{4}
=========找想同的单词出现=========
<html>
<head>
<script language="javascript">
var strSrc = "Is is the cost of of gasonline going up up?";
var re = /\b([a-z]+) \1\b/gi;
var arr = strSrc.match(re);
document.write("返回数组元素的个数为"+arr.length+"<br>");
document.write("返回数组元素的内容为[");
for(var i=0;i<arr.length;i++)
{
if(i<arr.length-1)
{
document.write("\""+arr[i]+"\",");
}else
{
document.write("\""+arr[i]+"\"]</p>");
}
}
</script>
<body>
返回数组元素的个数为3
返回数组元素的内容为["Is is","of of","up up"]
</body>
</html>
===============================
(?:pattern)
有时候必须要用(),但是又不想存到缓存区就用这个好了
情况有:
不可以将 industry|industries 简单写成 industr(y|ise)
会影响 缓存区的位置的,你这个()里放的都是些没有实际意义的东西
就可以写成 industr(?:y|ise)
(?=pattern)[这个不说情况打死也不知道再说什么]
正 向 预测先行 匹配
就是说 在 一堆里的东西附近一定要有这个,但是这个不放结果里,
更不放缓存里
比如在一大堆里有 window 2000 ,window NT ,window 2003
出现了N多次N多次,我现在只想对出现在2000 或者NT前的window操作怎么办?
就用这个 windows (?=NT|2000)
重要:匹配的结果 只是 windows 部分哦
如果把=变: 就匹配NT 或者 2000都进来了,虽然缓存里是不放的!!
--------思考---
window (?=NT|2000) series ,会不会匹配 window NT series
这要想死人的,别想了
记得 这个东西要么写在最前,要么写在最后
---------------
(?!pattern)反 向 预测先行 匹配
说明在一堆的相应处,不可以出现模式里的东西
和上面的基本类似!
window (?!NT|2000)
一大堆里有 window 2000 ,window NT ,window 2003
这下子只匹配 最后一个window
★特殊字符
RE里可以用(\)来表示 非打印字符 和 原义字符
\xn 匹配ASCII码等于n的字符n必须是两位16禁止数
\x41表示 A ,注意 \x041 表示 \x04 后面来一个1
这种方式一看就可以知道,可以匹配所有的字符,但是谁能记得呢???
\n 前面有() 当 反向引用 没有么 就只能0-7 ,ASCII码了
\nm 前面有() ,前小于n个, \n 当反向用 m普通字符
大于n个 nm一起上,当反响用
没有,都是一位的8禁止数, ASCII码了
\nml n小于3 最多(255)这些都是给高高手用的
ml8禁止数
ASCII码
\un unicode码了 n 四位16禁止数
\cx 匹配x 代表的控制字符
\cM 匹配 control + M 就是回车符了
x必须是字母,否则c就是c x就是x了
-----------
重要:在ASCII码里 16禁止的 00 -1F 之间的数字所表现的字符
是不可见的,也打印不出来
这些字符叫 控制字符
他们在一些特殊的场合使用
每个控制字符都有一个英文名称来表示意义和作用
在一些终端上,就是用control + M 来表示回车的,它没有回车键
可以按.
control + M 回车键
control + H 退各键
control + C 不知道什么键,反正有用
cmd里试吧 cmd里还有一个 control + i
看看吧
我们也可以用UtralEdit来看控制字符
view | views/list | ASCII table
-----------
\t 匹配制表符 等效于 \x09 \cI
\n 匹配换行符 等效于 \x0a \cJ
\v 垂直制表符 等效于 \x0b \cK
\f 匹配换页符 等效于 \x0c \cL
\r 匹配回车符 等效于 \x0d \cM
★字符匹配符
1[]
匹配[]里多个字符的任意一个
如果模式里有 原义] ,必须放第一位,紧挨[后面,这样就认得,
[]里面的\仍然做 转义 要用原义 \\
但是不知道 [ 原义怎么弄
2[^]
第一个是^ 就是排除,和上面对应的学
注意 ^不排第一 ,就是原义
3[a-z]
范围来了
注意:[]里要用 原义- 可\- [a\-z] [只有三个哦]
也可以把-放最前或者最后 [-a-z] [a-z-] [27个哦]
4[^a-z]
不在范围里的
\d 数字 等效 [0-9]
\D 数字 等效 [^0-9]
\s 等效[ \t\n\v\f\r] 任何空格 这里TMD是6个,有个空格看不见,呵呵
\S 等效[^ \t\n\v\f\r]
\w 等效 [A-Za-z0-9_] 26+26+10+1
\W 等效 [^A-Za-z0-9_]
. 匹配 所有的 除了 \n
(.)\1
匹配除 \n 外的两个连续的相同的字符
[\s\S] [\d\D] [\w\W]
这三个什么字符都匹配了
如果要匹配 原义. 要\.
看一个例子, 结巴翻译
把下面的话理顺一下:
"I...I...want...eat...eat...rice!"
"我....我要...吃...吃肥肠面!"
变"我要吃肥肠面!"
<html>
<head>
<script language="javascript">
var strSrc = "我....我要...吃...吃肥肠面!";
var strTgt= strSrc.replace(/\./g,"").replace(/(.)\1/g,"$1");
document.write(strTgt);
</script>
<body>
body!
</body>
</html>
==============这个我自己弄了半夜========
<html>
<head>
<script language="javascript">
var strSrc = "I...I...want...eat...eat...rice!";
var strTgt= strSrc.replace(/(\.)+/g," ").replace(/(\w+) \1/g,"$1");
//var strTgt= strSrc.replace(/\./g," ").replace(/e/g,"E");
document.write(strTgt);
</script>
<body>
</body>
</html>
==========I want eat rice!======================
★定位符
用于规定符合模式的字串出现的位置
这对验证非常有用
^ 匹配字串的开始位置 注意^必须写在模式的最前才有这个用
例子:
^o与ok 里的o匹配 hello里的o不匹配!
如果设置了multiline属性[这个还是要好好推敲,一般输入验证,也就那么一段]
^还会与行首匹配 \n \r之后的位置匹配
$ 匹配字串的结尾位置 注意$必须写在模式的最后才有这个用
如果设置了multiline属性
\n \r之前的位置匹配
\b
两边不全是\w
\B
非边界,应该好理解的
例子:
er\B 匹配 verb 的er 不匹配never 的 er
定位符实用例子
=============================
在对大段大段的文本操作的时候,
写模式要小心,
如果要匹配某一个单词
一定要/\bwin\b/g
边界一定要,英文单词单词里有单词很常见
-------------
再来一个例子,搜索义每而
可以这样
/[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+/
这可以搜索 邮箱地址了,但是搜不到我的,先不管
要注意的是这种不可以用的网页表单里
因为像这样
@.it33@it222.com.?
的不合法字串里包含有 合法的字串
用re.test()去验证,test不会关心合法字串出现的位置
所以,定位符还是要派上用场的
规范的写法/^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/
重要重要,但是你要在一堆里搜索,又不可以这样写了
哎,真够烦!
-----------------再来一个定位符例子
要在每行前加一个# ,注释每行,可以这样:
<html>
<head>
<script language="javascript">
var strTxt = "first line\n" +
"second line\n" +
"third line\n" +
"fourth line\n" +
"fifth line\n";
//document.write(strTxt.replace(/^/mg,"#"));
alert(strTxt.replace(/^/mg,"#"));
</script>
<body>
</body>
</html>
一定要加 flag m g!
=============================
★原义字符
一些字符已经定义为 元字符 了,如果要用他们的原义
必须用 \ 来转义
需要转义的字符有:
$ ( ) * + . [ ] ? \ / ^ { } |
对于/,由于写模式时需要用到它
所以要用/的原义,也必须转义 \/
==========
看一下优先级别
()最高
(ab)* ab组合后再和*组合
*
ab* b和*先组合后再和a组合
字符
没有什么例子
| 最低
a|bc bc组合后,再和a组合
==========
★实用例子
匹配空行[所有的空行(真空行,假空行都匹配)都匹配]
/^\s*$/
匹配假空行[就是说,直接换行的真空行不算,空行里有 空格,制表符等的空行]
^[\\s&&[^\\r]&&[^\\n]]\\s*\\n$ [查找脏空行的]
这个里有怎么使用 && 的.
就是说,开始是一个空白,但是这个空白不可以是直接就换行
匹配HTML标记
/<(\S+)(\s[^>]*)?>[\s\S]*<\/\1s*>/
匹配email
/[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+/
匹配相同的相邻的单词[小写情况]
/\b([a-z]+) \1\b/
匹配IP
/^\d{1,2}|1\d\d|2[0-4]\d|25[0-5](\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])){3}$/
===========
重要重要,程序做判断
返回true一定要放最后,把不合法的都放前面,一有不合法的,直接return掉!
实用程序举例一
校验ip地址是否合法程序
第一种:
function js_verify(addr)
{
var part_addr=addr.split(".");
if(part_addr.length!=4)
{
return false;
}
else
{
var part;
for(part in part_addr)
{
if(isNumeric(part_addr[part]))
{
if(parseInt(part_addr[part])<0||parseInt(part_addr[part])>255)
{
return false;
}
}
else
{
return false;
}
}
}
return true;
}
function isNumeric(str)
{
if(str.length==0)
{
return false;
}
for(var i=0;i<str.length;i++)
{
if(str.charAt(i)<"0"||str.charAt(i)>"9")
{
return false;
}
}
return true;
}
第二种方法:
function jsreg_verify(addr)
{
var reg=/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/;
if(reg.exec(addr)!=null)
{
//下面直接用字符串与数值比较,字符串将先转换成数值
if(RegExp.$1<0||RegExp.$1>255) return false;
if(RegExp.$2<0||RegExp.$2>255) return false;
if(RegExp.$3<0||RegExp.$3>255) return false;
if(RegExp.$4<0||RegExp.$4>255) return false;
}
else
{
return false;
}
return true;
}
第三种方法:
/*reg_verify - 完全正则表达式来判断一个字符串是否是合法的ip地址,如果是则返回true,否则返回false.*/
function reg_verify(addr)
{
var reg=/^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])(\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])){3}$/;
if(addr.match(reg))
{
return true;
}
else
{
return false;
}
}
用于检验的HTML代码:
<p>输入要检验的ip地址:<input type=text name=txtIp value="255.222.33.111"><br>
<input type=button name=btn1 value="测试JavaScript验证" onclick="alert(js_verify(txtIp.value))"><br>
<input type=button name=btn1 value="测试JavaScript和正则表达式验证" onclick="alert(jsreg_verify(txtIp.value))"><br>
<input type=button name=btn1 value="测试正则表达式验证" onclick="alert(reg_verify(txtIp.value))"><br></p>
============copy it into IE=====
<html>
<head>
<title>ss</title>
<head>
<script language="javascript">
function js_verify(addr)
{
var part_addr=addr.split(".");
if(part_addr.length!=4)
{
return false;
}
else
{
var part;
for(part in part_addr)
{
if(isNumeric(part_addr[part]))
{
if(parseInt(part_addr[part])<0||parseInt(part_addr[part])>255)
{
return false;
}
}
else
{
return false;
}
}
}
return true;
}
function isNumeric(str)
{
if(str.length==0)
{
return false;
}
for(var i=0;i<str.length;i++)
{
if(str.charAt(i)<"0"||str.charAt(i)>"9")
{
return false;
}
}
return true;
}
function jsreg_verify(addr)
{
var reg=/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/;
if(reg.exec(addr)!=null)
{
//下面直接用字符串与数值比较,字符串将先转换成数值
if(RegExp.$1<0||RegExp.$1>255) return false;
if(RegExp.$2<0||RegExp.$2>255) return false;
if(RegExp.$3<0||RegExp.$3>255) return false;
if(RegExp.$4<0||RegExp.$4>255) return false;
}
else
{
return false;
}
return true;
}
function reg_verify(addr)
{
var reg=/^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])(\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])){3}$/;
if(addr.match(reg))
{
return true;
}
else
{
return false;
}
}
</script>
</head>
<body>
用于检验的HTML代码:
<p>输入要检验的ip地址:<input type=text name=txtIp value="255.222.33.111"><br>
<input type=button name=btn1 value="测试JavaScript验证" onclick="alert(js_verify(txtIp.value))"><br>
<input type=button name=btn1 value="测试JavaScript和正则表达式验证" onclick="alert(jsreg_verify(txtIp.value))"><br>
<input type=button name=btn1 value="测试正则表达式验证" onclick="alert(reg_verify(txtIp.value))"><br></p>
</body>
</html>
======================over
实用程序举例二
---从统一资源定位符(URL)中提取各组件信息
问题分析:
当浏览器地址栏中输入http://www.it315.org/book/welcome.html或http://192.168.0.1:8080/index.html等URL地址时,浏览器内部将会作出怎样的具体处理呢?
示例程序代码:
<script>
var reg=/(\w+):\/\/([^/:]+)(?::(\d*))?([^# ]*)/;
var arr1="http://www.it315.org:8080/index.html".match(reg);
var arr2="http://www.it315.org/book/welcome.html#mark1".match(reg);
var str="协议,主机名,端口号,资源路径\n";
str+=arr1[1]+", "+arr1[2]+", "+arr1[3]+", "+arr1[4]+"\n";
str+=RegExp.$1+", "+RegExp.$2+", "+RegExp.$3+", "+RegExp.$4+"\n";
alert(str);
</script>
实用程序举例三
---创建能对多种常用格式进行验证的函数
<script>
var patterns=new Object();
patterns.ip=/^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])(\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])){3}$/;
patterns.email=/^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/;
patterns.date=/^\d{4}-(0?[1-9]|1[0-2])-(0?[1-9]|[1-2]\d|3[0-1])$/;//匹配日期格式2008-01-31,但不匹配2008-13-00
patterns.time=new RegExp("^([0-1]\\d|2[0-3]):[0-5]\\d:[0-5]\\d$");//匹配时间格式00:15:39,但不匹配24:60:00
function verify(str,pat)
{
thePat=patterns[pat];
if(thePat.test(str))
{
return true;
}
else
{
return false;
}
}
alert(verify("00:00:11","time")+","+verify("it315@it315.org","email")+","+verify("192.168.1.1","ip")+","+verify("2003-00-31","date"));
</script>
===================================
相关推荐
在“UDP-Learnning-master”目录下,你可能会找到示例代码、练习和教程,帮助你理解如何使用UDP进行实际的网络编程。通过分析和运行这些代码,你可以深入学习UDP的工作原理,掌握如何在不同的场景下有效地利用UDP...
在"alg-learnning-master"这个压缩包中,我们预期会找到一个组织良好的源代码结构,可能包括以下几个部分: 1. **src**:存放所有Java源代码文件,每个文件可能对应一个或多个算法的实现。 2. **test**:单元测试...
java8 集合源码分析 ###解决过问题汇总 1.post请求传递的参数,接口必须要接收,否则报错; Unrecognized field , not marked ...(1)原因:项目中用了MappingJackson2HttpMessageConverter默认要求必须存在相应的字段...
leetcode 跳跃 算法学习 算法有用吗? 我是一名从事前端开发的程序员,我经常问自己学习算法有用吗。因为前端开发很多时候是重现设计页面,调用后端接口,改善用户体验等。偶尔碰到的时候,也不过是使用一些实现好的...
Q学习是一种强化学习算法,主要用于让智能体在与环境的交互中学习最优策略。它基于贝尔曼优化方程,通过迭代更新Q值来逼近理想的行为。在这个“Q学习matlab代码+注释”中,我们可以期待看到如何用MATLAB实现这一算法...
意图控制matlab仿真代码LQR-积分-Q-学习 该存储库提供了用于重现出版物中提供的模拟结果(图 1(a)、(d))的开源代码: “Lee、JY、Park、JB 和 Choi,YH,用于连续时间线性系统自适应最优控制的积分 ...
藏经阁-Analysis of dropout learnning.pdf Dropout 学习是一个 regularization 技术,旨在解决深度学习中 overfitting 的问题。它通过随机 dropout 一些隐层单元和输入单元来减少网络的容量,避免过拟合。 ...
《OpenCV学习指南》 OpenCV(开源计算机视觉库)是一个强大的计算机视觉和机器学习软件库,被广泛应用于图像处理、计算机视觉以及人工智能领域。它提供了丰富的函数和模块,可以帮助开发者实现诸如图像读取、图像...
台大机器学习基石的对应教程,配合台大的视频学习更加.
"Learnning-Service: Service学习过程中的Demo"是一个项目,旨在通过具体的示例帮助开发者掌握Java相关的服务开发技术。在这个项目中,我们可以深入探讨几个关键的知识点: 1. **Java基础知识**:作为项目的标签,...
- "netty-learnning-master" 文件夹很可能是项目源代码的根目录,包含了服务器端和客户端的实现。 - 服务器端的启动类通常会初始化一个 ServerBootstrap,配置好 EventLoopGroup(工作线程组),并绑定监听端口,...
DBN(Deep Belief Network,深度信念网络)是一种在深度学习领域广泛应用的神经网络模型,由Geoffrey Hinton及其团队在2006年提出。这个DBN-master.zip文件包含了一个DBN的入门项目,旨在帮助初学者理解并实现DBN...
#### `auto-learnning enable` 启用自动学习功能。这意味着设备可以自动学习连接到其端口的设备的MAC地址,并将其添加到MAC地址表中,以便进行数据转发。 #### VLAN翻译配置 - `vlan-translate ingress-port epon...
**Octave工具在机器学习中的应用** Octave是一款开源的数值计算软件,它与MATLAB高度兼容,使得用户能够在不购买昂贵商业软件的情况下,进行复杂的数值计算和数据分析。这款工具在机器学习领域得到了广泛的应用,...
在这个"learnning03.rar_matlab 跳频_扩频系统仿真_扩频通信系统_跳频扩频系统_跳频系统 MATLAB"项目中,我们可以深入学习和理解跳频扩频系统的原理和MATLAB仿真过程。 首先,跳频扩频系统的基本工作原理是:发射端...
在"js_plugins_learnning-master"这个文件夹中,你可能找到了一些示例插件的源代码。通过深入分析这些代码,你可以更深入地了解上述知识点,并实践如何应用这些理论到实际项目中。同时,也可以借鉴优秀插件的设计...
《Learning OpenCV中文版》是一本专为中文读者编写的关于OpenCV库的教程书籍,旨在帮助读者深入了解和掌握OpenCV在计算机视觉领域的应用。OpenCV(开源计算机视觉库)是一个强大的工具集,广泛用于图像处理、机器...
Guy Steele's keynote at the 1998 ACM OOPSLA conference on "Growing a Language" discusses the importance of and issues associated with designing a programming language that can be grown by its users.
请看我博客里的说明: http://blog.csdn.net/singlerace/archive/2006/12/11/1439048.aspx
You're expected to have a basic understanding of Linux commands and Python. Table of Contents Getting started with ROS Understanding basics of differential robots Modeling the Differential Drive ...