经过各位读者和出版社的辛苦努力,《正则指引》终于上市了,以下是主要的购买链接:
亚马逊:http://www.amazon.cn/%E6%AD%A3%E5%88%99%E6%8C%87%E5%BC%95-%E4%BD%99%E6%99%9F/dp/B007X6O6J0/
当当:http://product.dangdang.com/product.aspx?product_id=22702127
京东:http://book.360buy.com/10972570.html
China-Pub:http://product.china-pub.com/199266
有趣的是,预售阶段就登上了京东的24小时分类畅销榜,感谢大家的厚爱。
From Life Sailor, post 《正则指引》上市了
之前我写了一篇《坚持了两年之后,小朋友突然不想去打冰球了…》,本来是无心之作,没想到收到了很多留言,我自己也获益不少。 本来,我以为解决了小朋友的问题,此事就这样过去了。没想到的是,暑假过后,冰球训练重开,他又老调重弹:“我不去了,我不想打冰球了……”。 这可叫我如何是好?听到他嘟嘟囔囔说这一切的时候,我心里百感交集。 成年人的生活里总是有忙不完的事情,对应的,也希望一切井井有条、按部就班。因此,这样“意外”的变数,总是第一时间让人心生无奈和烦恼:天哪,怎么会这样呢?为什么会这样呢? 不过,基于之前的经验,借鉴大家的留言,这次我显然更有心理准备一些,起码不会慌乱。 之前我写过,如果父母多阅读一些高质量的育儿专著,有助于把自己的期望水平“降”到合适的程度,就不会那么焦虑甚至抓狂。 (more…)
认识Michael很偶然,但我也很幸运,因为我见证了一个“打冰球的好孩子”的成长。 最早认识Michael是在冰球队的夏季体能训练上。那时候这群孩子还只有六岁左右,每次训练都是家长送来,在旁边观看陪伴,再接回家。但是,我很快发现有个孩子不一样,家长送他来就回家,他靠自己换好全身装备,训练完自己洗澡更衣,再由家长接回去。看起来,他好像完全没有其他孩子那种“害怕独处”的感觉。 于是我问他:“小朋友,你这么勇敢,你叫什么名字呀?” 他说:Michael。 我尝试复述他的名字,好几遍都不成功,因为我总听成“米歇”,最后他耐着性子慢慢说,我仔细听才发现最后还有个音节,嘴要更扁一点,舌头往上垫,才可以念出来,类似“米歇-厄尔”。其实这个名字写出来大家都认识,英文里读作“迈克尔”,无奈德语的发音规则很严格,字母i不会像英文那样有两种读音,结尾的el又一定要发音,所以就成了“米歇-埃尔”。 (more…)
偶然刷到一篇文章,说的是“贵族家长”群体给小朋友安排的活动:冰球、马术…… 我有点诧异,原来“冰球”也被贴上了“身份”的标签。想想自家小朋友的情况:赶上打折花了400多欧元买的全套护具,80元买的二手冰球包,每个月60欧元的俱乐部费用……想了想,似乎很难和“贵族”联系起来。 只不过,他已经坚持打冰球到了第四年,我们的生活确实有不小的变化。写下来,既是对自己有个交代,也可以作为“贵族运动”的现身说法。因为在我看来,如果非要说它是“贵族”运动,也只能“贵”在高(时间)投入、高产出而已。细细想来,我们的生活,已经被冰球深深的影响了。 (more…)
一 很多人关心,我们父子给M写了道歉信之后,对方是否有回应。 答案是:到目前为止,还没有任何回应。不过比较特殊的是,写完信之后德国小学就开始放秋假,学生不用去学校,既然见不到,也就不可能收到任何回应。 老实说,我觉得对方父母是有点反应过度的。这些年我的一条深刻经验是,如果出现分歧、矛盾,越早、在越低的层面直接面对,就越容易解决。许多小的矛盾之所以越闹越大甚至无法收场,往往都是经过了很多演绎、传话,而没有在一开始就开诚布公地面对。 试想,如果自己的孩子收到写着“我要杀了你”的信件,哪怕一开始很惊慌甚至愤怒,但仔细想一想,毕竟还有很多信息是未知的——比如对方是谁,平时言行如何,为何要写这样的信…… 更好的办法或许是先去直接寻求这些问题的答案,而不是直接把信交给家长委员会,走“公事公办”的路子。 我当然承认,“公事公办”无可厚非,对方家长也有这样的权利——所谓权利,就是“有资格做对方不喜欢的事情,人家还拿你没办法”。既然有这样的权利,就需要尊重。 所以,“严于律己,宽于待人”的确是与人相处的重要法则:我不会选择这么做,但我能理解和尊重你这么做的权利。 也有人问,那将来你遇到M的父母,会不会紧张? 答案是:不会。 (more…)
一 收到S老师邮件的时候,我刚刚胆战心惊地做完第一次德语技术分享,还在享受着同事们的鼓励。猛然间就收到一封邮件:“您的孩子在学校参与了一起性质严重的事件,您必须来学校面谈,请从以下时间段中选择……” 什么?“性质严重的事件”?我揉了揉眼睛,确认自己没有看错。再把这段文字贴到谷歌翻译里,确认自己没有理解错。 我没有看错,也没有理解错,就是“性质严重的事件”。好吧,既然“性质严重”,那谈话肯定是越早越好,最早的日期是第三天。我紧赶慢赶,回信确认了最早可能的谈话时间,虽然德国人通常都不期待能这么快收到回复。 去接他回来的路上,我发现他一切正常,完全看不出任何异样。于是,我也没有表现出任何异样,只是依照惯例,问他当天发生了什么,在学校开心不开心。 得到肯定的答复之后,我心生疑惑,看起来和“性质严重”完全不搭边。那会是什么事情呢? 我又问他,有没有和同学吵架、打架,是不是被人欺负了不敢说。但是,答案全都是“没有”。 我满心怀疑,又按捺不住,直接问:“既然一切都挺好,为什么S老师给我发信,说让我来学校跟她谈话呢?”我担心“性质严重”会吓到他,故意隐去了这个词。 他的满面春风在那瞬间凝固了,喃喃低语道:“好吧,原来是那件事,我还以为她不会跟你说。” (more…)
在2024年之前,我从来没想过自己有一天还可以加入乐团,甚至参加音乐会演奏。我只是个普通中年人,在之前文章里说过,上世纪八十年代随大流弹了十年手风琴,考过六级(当时最高八级)之后就彻底放弃了。直到二十多年后,在上海工作时才重新开始弹琴,当时有幸跟夏老师学了两年,打开了感官,懂得了音乐的世界远远比考级要广阔和美妙。再往后,就是自己看Youtube学习了一些乐理知识。因为德国几乎每个城市都有很多音乐学校,2023年末,我给本市的音乐学校写信,询问是否可以参加手风琴课程。通过回信我才知道,原来不只是“每个城市都有很多音乐学校”,而且“每个城市都有很多乐团”,哪怕是手风琴乐团。就这样,阴差阳错的,2024年初,经过简单的试奏,我加入了本市的手风琴乐团。虽然我是乐团新人,仍然有很多要学习的,但是一年下来,确实有不少感受。如果读者朋友也对音乐感兴趣,或者想让孩子学习音乐,也许我的感受可以提供一些参考。 (more…)
View Comments
余老师,我说一些前面没有被指出的错误吧!
引子:第 IV 页的 re.search 和 re.findall 两个函数中的 pattern 和 string 都写反了
P3:例 1-3 中关于 Python 的说明一行"能匹配则返回 RegexObject",应该是"Match object"
P5:第二段中第三行中“请参考第 241 页”,应该是“21 页”吧
P34:例 3-3 中的第二个 re.search 中 re.search(idCardRegex, "1101018001017016") != None 的结果应该为 False,因为给定的数字是 16 位的,而非 15 位
P38:第二段结尾部分中,邮箱的用户名不可能为空吧?所以 {0,64} 最好改为 {1,64},同理还有第 39 的相关部分;还有 38 页的前一部分用 [\w.]{0,64} 来匹配用户名,但是到了 38 页的最后一段和 39 页的例子当中,却变成了 [-\w.]{0,64},多了一个 '-',我记得邮箱中好像不允许出现 '-' 的
P40:第一行代码 re.search(idCard, "1101018001017016") != None 的结果应为 False
P41:表中最后一行对分钟的匹配 (0?[1-9]|[0-5]\d|60) 中间出现了重复,改成 (0?[1-9]|[1-5]\d|60) 估计更好一点
P41:最后一段,“仔细分析 tag 中可能出现 > 它只可能作为属性...”该句中"它"前面应该加一个逗号
抱歉回复晚了。
非常感谢你的细心回复,这些地方确实是我弄错了,惭愧,我已经把它们全部收录到勘误列表中了。
如果你看到其他错误,请继续告诉我。
另外,希望这本书对你有用。
刚才的回复中,
“P40:第一行代码 re.search(idCard, “1101018001017016″) != None 的结果应为 False”
应该改为“P40:第一行代码 re.search(idCardRegex, “1101018001017016″) != None 的结果应为 False“,一不小心写错了。。。
老师您好,在《精通正则表达式》P162 页中有个测试,就是[0-9]* 这个正则表达式是否会保存 a ▲1234 num这个状态的问题。我测试了一下,我使用ab[0-9]*123cd依然能够匹配ab123cd,这也就说明它是会保存该状态的,但是在P164页的答案中却说不会保存?麻烦您解释下
你好,这里书上说的是没错的。
用[0-9]*匹配a1234,其结果是可以匹配,但匹配的字符串是空,实际上就是a之前的空字符串,整个匹配到这里就结束了,不会继续试探,所以不存在状态a ▲1234 num。
用ab[0-9]*123cd能匹配ab123cd,前面新增了ab,所以[0-9]*开始匹配时,是从1开始的;如果你需要类比,则应当用ab[0-9]*123cd匹配aba123cd,这样看得很明显:)
余老师您好,73页表达式匹配hostname中疑似发现一个错误。
原文:
(?=[-a-zA-Z0-9.]{0,255}(?![-a-zA-Z0-9.]))((?!-)[-a-zA-Z0-9]{1,63}\.)*((?!-)[-a-zA-Z0-9]){1,63}
我认为第二段的(?!-)[-a-zA-Z0-9]不应再加上括号,否则环视(?!-)对每次[-a-zA-Z0-9]匹配都生效,所以不能匹配形如foo-bar的hostname
正确的应该是
(?=[-a-zA-Z0-9.]{0,255}(?![-a-zA-Z0-9.]))((?!-)[-a-zA-Z0-9]{1,63}\.)*(?!-)[-a-zA-Z0-9]{1,63}
望确认。
你说的没错,感谢指出,我已经收录到勘误列表里了。
补充
64页中间一段中
\Z和\的主要区别在于:
应该是
\Z和\z的主要区别
是的,这里确实是我写错了,非常感谢你指出,我已经收录到勘误列表里面了。
老师,麻烦您回答下23楼的问题,谢谢
已经回答了:)
余老师,最近有发现了一些小错误,可能与上面的某个重复,T_T。
P43,中间部分,“正则表达式是(jeff|jefferey)还是(Jeffrey|jeff),结果是...”这一句如果要与下面例子对应的话,应该改为“正则表达式是(jeff|jeffrey)还是(jeffrey|jeff),结果是...”。
P49,倒数第二行中的表达式“”前少了一个“/”,应该改为""。
P55,3.4节最后一段,“为了使代码简洁和易于”,后面好像少了一些内容。
P56,例3-36中,第二行与第一行重复,第三行的“# => True”应该删掉;该页的倒数第三行的正则表达式中,"{2"之后少了一个"}",应该为"{2}"。
P60,例4-2的结果不对,应该为“tomorrow I will wear in brown standing in row 10 next to the rowdy guy”。
P62,例4-3的第一行正则表达式中,“last line”前面多了一个”\r“。
P63,例4-4第一行中,“ast line”前面少了一个“l”。
P71,例子4-17下面一段,“其中(?!\一种组合”,读起来有点不知所云。
P75,例4-21中的(?!=ab)应为(?<=ab)。
P78,中间的例子(原本编号应为例 4-23)没有编号,这就造成了P79中第一段最后一行“具体的例子可见例4-24”和该页最后一段的“代码见例4-25”指向错误。
P87,第二段下面的正则表达式结尾少了一个“$”;例5-6中的“# enable multiline and extended mode”去掉“multiline mode”;下一行的“# start of whoe regex”应为“# start of whole regex”,同理还有P88页的开头。
P88,表格下面那一段的第一行“例5-6同时指定了...”应为“例5-5同时指定了...”。
P90,例5-7中最后一句的执行结果部分,后两个词各多一个“B”。
P91,例5-8下面一段第二行“\1不在区分大小写模式...”应为“\1不在不区分大小写模式...”,第三行“\1处在区分大小写模式...”应为“\1处在不区分大小写模式...”。
P98,表6-7下面那一段的倒数第二行,"b)"实为"c)"。
P101,例6-9的最后一行,“re.search(r"[()", "(") != None”应为“re.search(r"[(]", "(") != None”;下面段落的倒数第三行,“它可以匹配除^、a、b之外的任何字符”,应该是“它可以匹配的字符是^、a、b”。
P102,6.2.1节的例子中的最后一行,正则表达式周围没有包含在两个分割符内,一般取分割符为"/"。
P107,表6-10的第三个正则表达式“(ab)+”应该是“a+(bc)”。
P116,例7-9下面的一段的最后一行,“\s匹配\S不能匹配的字符”虽然说法没错,但是如果与前面对应的话,改成“\S匹配\s不能匹配的字符”好一点。
P118,例7-12下一段的第二行,"\b\regex\b"应为"\bregex\b"。
P119,倒数第二段的参考页应该是253页,倒数第一段的参考页好像应该是234页。
P120,第一段的参考页好像应该是第6页,而不是105页。
P135,脚注1中的页面引用出了问题,我感觉应该是144页。
P136,最后一行,“需要关注只是”,改成“需要关注的是”好一点。
P144,第三段的否定逆序环视写错了,应为“?<!”,书上写成了“?!<”。
P147,表格中关于 Python 的部分,Python 中没有 re.find 这个函数,我感觉您的意思好像是再说 re.findall,而后面的“逐步进行”应该为“一次性进行”。
P148,例9-3的题目写错了,应该是“函数式处理...”。
P163,例9-14的第二行中的正则表达式好像多了一个"."。
P165,例9-16中的正则表达式感觉还是不能拿来判断闰年,因为同为闰年或者非闰年时,为返回不同的结果;我觉得改为
"return int(str) % 400 == 0 or (re.search(r"\A\d{2}(?!00)([02468][048]|[13579][26])\Z", str))"
可能会好一点;但该表达式也不是通用的,因为它不能判断五位或以上位数表示的年份,我尝试用多选分支写了个判断闰年的通用表达式,但是非常复杂,感觉失去了使用正则表达式的意义。
P239,最后一段的否定逆序环视写错了,应为"(?<!...)"。
P245,第一段的 re.searh 应该全部为 re.match,最后一句的执行结果为 False。
P247,倒数第二个正则表达式的执行结果“One TWO THREE”应为“One Two Three”。
Hello,非常感谢你指出的问题,我已经全部收录到勘误列表里去了。
在本书繁体版要面世之前,可以解决这么多的错漏,真是高兴又惭愧。
P49,我刚刚说的有点问题:倒数第二行中的表达式“”前少了一个“/”,应该改为“”。
不过,虽然有点小错误,这本书深入浅出,看完后还是受益匪浅的,谢谢余老师。
哇,原来上一句是被blog自动给拦截了,T_T。总之就是P49页的倒数第二行的正则表达式有点小问题,余老师应该可以看到。
同理,P60的html标签也被转义了,不过老师应该能发现错误。
余老师您好,以下是我根据您博客中最新的勘误表修改后发现书中的一些问题。
下面是从excel中复制出来的,格式有些乱。
页数 页内位置 修改前 修改后 说明
15 1.8节第二段第二行 Per Perl
48 例3-22上两行 原生字符串(P93) - 应为P9或者P96
56 例3-36 - - 前两行相同
61 第二段第二行 具体情况(P59) - 应为后边Unicode处某内容
65 例4-10第三行 lin1 line1
65 例4-10该页倒数第三行 lin1 line1
68 4.3第二段第一行 ][^>]*> ]*> 保持和第二章勘误的修改一致
69 图4-2上数第二段 - - 最后一个单引号格式与前面的不统一
69 图4-2上数一段 - - 最后一个单引号格式与前面的不统一
69 图4-2中间的表达式 ('[^']*' "[^"]*" [^'">])+ ('[^']*'|"[^"]*"|[^'">])+ 中间的表达式缺少了|
70 图4-3 - - 第二行和第四行的匹配位置反了
110 注释1 - - 书中标注的是第一行的ASCII编码后边,注释内容是Unicode编码,应该改为第二行Unicode编码后
118 最后一行 表7-4举列列出 表7-4举例列出
141 第5段最后一句 所以下面几种讨论“不超过63个字符”部分的匹配 - 但是下面讨论的是不出现两个连续的点号的匹配
143 第二段第二行 精确是则要保证正则表达式 精确则是要保证正则表达式
147 表格下第二段第一句 如果使用函数式正则表达式采用的是面向对象式处理 如果正则表达式采用的是面向对象式处理 应该没有“使用函数式”几个字
150 第二组列表下一段第三行 。, 。 最后有一个。和一个,相连
150 第三组列表(1) (?=\A.{6, 12}\z) (?=\A.{6,12}\z) {6,12}中间多了个空格
154 第一行 同时需要留下的部分 同时留下需要的部分
157 代码下面一段第二行 deletgate delegate
158 倒数第二行 将它设定为一个小于n的正数,则会进行n-1次切分(只有Python是例外,它会切分n次),返回数组的最后元素包含了“正则表达式第n-1次匹配右侧的所有文本” - 这里第一次用的n是指最多能切分的次数,而后边的n是指设定的切分次数,前后n的含义不统一
162 9.4.1第三行 如果只需要查找;同样, 这中间应该少了部分内容
162 9.4.1第三行 如果只需要判断字符串开头以某个固定字串开头,以某个固定字串结尾 如果只需要判断字符串以某个固定字串开头,以某个固定字串结尾 应当去掉“字符串开头”中的“开头”两字
234 第一段最后一行 因此\d也可以直接写成字符串\\d 因此\d也可以直接写成字符串\d 多出了一个字体错误的\
235 表格中的忽略优先量词 ?* ?+ *? +?
240 第一段代码后两行 - - 注释中的#格式有误
245 14.3.6标题 re.findall(pattern, sting[, flags]) re.findall(pattern, string[, flags])
247 倒数第二行代码 - - 回调函数toUpper在上文中没有出现
勘误12行 页数 25 35
勘误14行 页数 31 35
勘误17行 页内位置 第2段 第1段
勘误54行 页内位置 5.4倒数第3行 5.4倒数第3段
勘误54行 修改前 例5-6同时制定了两种模式 例5-6同时指定了两种模式
勘误57行 页内位置 例5-8下面第1段第2行 例5-8下面第1段第3行
勘误62行 页内位置 例6-9下面一行的倒数第3行 例6-9下面一段的倒数第3行
这本书写得很好,以前对正则表达式总是一知半解的,每次用都要现查,学的一点都不彻底,这回很多东西都弄明白了,感谢余老师。
Hello,感谢指出。
你能直接在Excel中标注,然后发给我吗?我给你发邮件了。