为了账号安全,请及时绑定邮箱和手机立即绑定
2. 正则表达式规则

Tips: 正则表达式= 特殊字符(元字符) + 文本(普通字符)上面的公式其实就是一个完整的正则表达式,你可以简单的将正则表达式理解为是一种语言,元字符就是它的语法,普通字符就是单词。我们来看一个简单的正则表达式的例子:下面是一个自动化配置 terraform 的一个配置文件 main.tf。我们会用正则表达式 grep -E ‘(image_id|key name)’ main.tf 来同时匹配这两个字段。对于不太了解正则表达式的人来说这段简单的公式是有点云里雾里的。下面我们来具体看下正则表达式具体语法规则有哪些,然后再回过头来看就一目了然了。

Ruby 正则表达式

正则表达式是使用一串字符来匹配一系列符合某个语法规则的字符串,通常被用于检索和替换符合模式的文字。本章节中我们讲学习在 Ruby 中如何使用正则表达式。

1. 正则表达式简介

在编写爬虫的过程中,我们需要解析网页的内容。那么作为文本解析利器的正则表达式当然可以运用到我们的爬虫开发中。其实页面解析过程无非是从海量的字符串中将我们所需要的数据匹配并剥离出来,所以在正式的爬虫开发中正则会经常被用到。正则表达式是对字符串操作的逻辑公式。在提取网页的数据的时候,我们需要把源代码转换成字符串,然后通过正则表达式匹配想要的数据。在我们开始使用正则表达式进行模式查找之前,我们需要先熟悉一下正则表达式里面的字符的基本含义,熟悉了它们之后,我们就可以很方便的书写一些正则表达式进行模式匹配了。

3. 正则表达式选项

在 Ruby 中我们可以在正则中添加一些选项,改变正则的行为。选项时机简介(调用的时机)i正则表达式不区分大小写m点匹配换行符x忽略空格要使用这些选项要在正则表达式结束后在末尾添加选项字母。实例:> "abc".match?(/[A-Z]/i)=> true

Vim 中使用正则表达式

相信大家对于正则表达式的概念应该不会陌生,正则表达式以一种能够快速匹配文本的方式,同样的作为时下最流行的编辑器,Vim 中也支持使用正则表达式,这个小节就让我们一起来看下如何在 Vim 中使用正则表达式。

1. 创建正则表达式

在 Ruby 中,我们在两个/之间定义正则表达式,最简单的正则表达式匹配一个单词或者一个字符串。实例:> /a/.class=> Regexp我们还可以使用Regexp类将字符串实例化为正则对象。实例:> regexp = Regexp.new("a")=> /a/除了上述方法还可以使用%r[]实例:> regexp = %r{\w+}=> /\w+/

2.3 使用正则表达式

上面是比较简单的 URLconf 配置形式,Django 框架中可以使用正则表达式来进一步扩展动态 URL 的配置,此时 urlpatterns 中的不再使用 path 方法而是支持正则表达式形式的 re_path 方法。此外,在 Python 的正则表达式中支持对匹配结果进行重命名,语法格式为:(?P<name>pattern),其中 name 为该匹配的名称,pattern 为匹配的正则表达式。 这样我们可以有如下的 URLconf 配置:# hello_app/urls.pyfrom django.urls import re_pathfrom . import viewsurlpatterns = [ re_path('articles/(?P<year>[0-9]{4})/', views.year_archive), re_path('articles/(?P<year>[0-9]{4})/(?P<month>0[1-9]|1[0-2])/', views.month_archive), re_path('articles/(?P<year>[0-9]{4})/(?P<month>0[1-9]|1[0-2])/(?P<title>[a-zA-Z0-9-_]+)/', views.article_title),]注意:这里使用正则表达式的 URL 匹配和前面的普通的动态 URL 匹配有一个非常重要的区别,基于正则表达式的URL 匹配一旦匹配成功就会直接跳转到视图函数进行处理,而普通的动态 URL 匹配则会找到最长匹配的动态 URL,然后再进入相应的视图函数去处理:[root@server ~]# curl http://127.0.0.1:8881/hello/articles/1998/12/testhello, 1998 archive可以看到,这里并没有匹配到第三个 re_path 的 URL 配置,而是直接由第一个 re_path 的视图函数进行了处理。

2. 使用REGEXP正则表达式查询

以 student 表为例,使用正则表达式查询出姓王的教师:SELECT * FROM student WHERE name REGEXP '^王';查询结果如下图:使用正则表达式查询 name 字段中包含小字的数据:SELECT * FROM student WHERE name REGEXP '小';查询结果如下图:以 teacher 表为例,使用正则表达式匹配符合邮箱格式的数据:SELECT * FROM teacher WHERE email REGEXP '^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$';查询结果如下图:Tips:如上图所示, 其中 ^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$ 为符合邮箱匹配规则的正则表达式,查询结果 email 的值如果不满足此正则表达式,则该条数据不会被查询出来。

2.1 正则表达式思维

正则表达式按照字节或者字符作为匹配单位的。而不是单词或者句子。比如上述表达式我们简化下grep -E ‘bat’。 本质上不是匹配的 bat 这个单词,而是匹配 b,a,t 作为连续字符。字符组:[0-9]:中括号作为正则表达式结构体,可以允许匹配结构体内任意匹配字符。比如这里的 [0-9] 匹配 0-9 之间任意一个数字。Tips: 只有字符组内连字符 - 才是元字符。多选结构:这就是我们刚才演示的例子。(a|b)——小括号中|作为元字符意思是或意思可以同时匹配 a、b.下面我们来看下常用的具体表达式。

3. Vim 正则表达式引擎

Vim 的正则表达式引擎和 Perl 相比不太一样。语法更接近于 POSIX。对于我们一般使用关了 Perl 正则表达式开发人员来说,使用方式的冲突会很不友好。但是通过 magic 开关设置可以满足不同的使用场景。

2. Shell 正则表达操作

在学习正则表达式的操作之前我们需要了解下 POSIX 及正则表达式的分类。

2.2 正则表达式修饰符

正则表达式可以包含一些可选修饰符来控制匹配的模式。修饰符被指定为一个可选的标志,多个标志可以通过按位 OR(|) 它们来指定,如 re.I | re.M 被设置成 I 和 M 标志。下表列举了常用的正则表达式修饰符:修饰符描述re.I使匹配对大小写不敏感re.M多行匹配,影响 ^ 和 $

MySQL 中使用正则表达式

前面小节介绍过使用 LIKE 模糊查询包含指定内容的字段的结果集,本小节介绍正则表达式相关的基础知识,学习之后,可以使用正则表达式来查询更加符合需求的字段内容。

1.1 正则表达式是什么

正则表达式 (regular expression)是一些具体有特殊含义的符号,组合在一起的共同描述字符或字符串的方法,通俗来讲正则为描述同一类事物的规则,例如我们生活中描述可以飞行的是事物,则满足这条规则的可以是鸟,蝴蝶,也可以是飞机等。在 Linux 系统中,正则表达式通常用来对字符或字符串来进行处理,它是用于描述字符排列或匹配模式的一种语言规则。

1. 正则表达式概念

正则表达式(英文:regular expression),是一种文本模式。它赋予了 Vim 描述和分析文本的能力。可以根据需要,高效地增删改查各种类型得文本和数据。实际工作中,无论是开发还是运维、测试等从事IT的人来说。正则表达式都是工作中必不可少的。它可以满足高效简洁地查找某些复杂规则的字符语句的需要。比如说以下几个场景:对身份证号码 / IP 等匹配检查网页对登陆名为手机号码匹配特定规律字符串的处理提取邮件某些开头规律行可以结合其他额外工具(grep、sed 等)高效处理文本

1.2 为什么要用正则表达式

我们知道正则表达式是一个描述字符排列或模式匹配的规则,我们可以利用它来制定自己的规则,获取到我们想要的结果等。在后续的 Shell 三剑客 grep/awk/sed Shell 的学习中,我们会结合正则表达式与这些命令进行结合使用,来实现更强大的文本处理功能。正则表达式是我们 Shell 学习的核心也是难点,在 Linux 中一切皆文件,多文件的处理可以覆盖我们日常工作的 90%,所有熟练掌握正则表达式显得尤为重要,在之后灵活配合其他命令可以非常方便的满足我们的日常处理需求。

2.2 正则表达式操作

在 Linux 中正则表达式用来处理文本,在此我们使用 grep 工具对正则表达式进行操作,grep 为文本过滤工具,在 grep 命令中默认使用的时候基本正则表达式,可以使用选项 -E 来开启扩展正则表达式,按照指定的正则表达式取出我们需求的内容。2.2.1 字符匹配在字符匹配前需要先学习。.: 匹配任意单个字符,例如:[root@master reg]# cat test.txt sheshs1e[root@master reg]# grep "s.e" test.txt shes1e. 匹配必须为字母 s 与 e 中有任意单个字符。[] : 匹配指定中括号范围内的任意单个字符,例如:[root@master reg]# cat test.txt sheshs1e[root@master reg]# grep "s[a-z]e" test.txt she[root@master reg]# grep "s[1-9]e" test.txt s1e[root@master reg]# grep "s[[:alnum:]]e" test.txt // 匹配字符或数字 shes1e[root@master reg]# grep "s[[:alpha:]]e" test.txt she[root@master reg]# grep "s[[:digit:]]e" test.txt s1e中括号内可以利用元字符来表示。[root@master reg]# cat test.txt sheshs1e[root@master reg]# grep "s[^[:digit:]]e" test.txt she[root@master reg]# grep "s[^a-z]e" test.txt s1e如上,匹配的元字符取反,也就是不包含匹配的内容。2.2.2 次数匹配次数匹配用在指定的字符后面,表示指定匹配到前面的字符出现多少次。*: 匹配前面的字符任意次(0 次或无数次),例如:[root@master reg]# cat test2.txt sssshsheeehell[root@master reg]# grep "s*" test2.txt sssshsheeehell 如上匹配字符 s,0 次或多次。\?: 匹配前面的字符 0 次或 1 次,例如:[root@master reg]# cat test2.txt sssshsheeehell[root@master reg]# grep "s\?h" test2.txt ssssh # 匹配最后的shsheee # 匹配shhell # 匹配h[root@master reg]# grep -E "s?h" test2.txt sssshsheeehell如上匹配 s 可以存在 0 次,或者存在 1 次之后需要有 h 字符,注意利用选项 -E 开启扩展正则表达式,相较于基本正则表达式不需要 \。+: 匹配前面的字符至少 1 次,例如:[root@master reg]# cat test2.txt sssshsheeehell[root@master reg]# grep "s\+h" test2.txt ssssh # 匹配sssshsheee # 匹配sh[root@master reg]# grep -E "s+h" test2.txtsssshsheee如上匹配 s 至少存在 1 次或无数次。\{m\,}: 匹配前面的字符至少 m 次(默认工作在贪婪模式下,? 取消贪婪模式),例如:[root@master reg]# cat test2.txt sssshsheeehell[root@master reg]# grep "s\{1,\}" test2.txt sssshsheee[root@master reg]# grep -E "s{1,}" test2.txt sssshsheee[root@master reg]# grep "s\{2,\}" test2.txt ssssh[root@master reg]# grep -E "s{2,}" test2.txt ssssh匹配字符 s,最少 1 次。\{,n}: 匹配前面的字符最多 n 次(默认工作在贪婪模式下,? 取消贪婪模式),例如:[root@master reg]# cat test2.txt sssshsheeehell[root@master reg]# grep "s\{,2\}" test2.txt sssshsheeehell[root@master reg]# grep -E "s{,2}" test2.txt sssshsheeehell匹配字符 s,最多 2 次。\{m,n\}: 匹配前面的字符至少 m 次,至多 n 次,例如:[root@master reg]# cat test2.txt sssshsheeehell[root@master reg]# grep "s\{1,2\}" test2.txt sssshsheee[root@master reg]# grep -E "s{1,2}" test2.txt sssshsheee匹配字符 s,1-2 次之间。.*: 匹配任意字符任意次数。2.2.3 位置锚定^: 行首锚定,用于模式最左边,例如:[root@master reg]# cat test2.txt sssshsheeehell[root@master reg]# grep "^s" test2.txt sssshsheee匹配以 s 开头的行。$: 行尾锚定,用于模式最右边,例如:[root@master reg]# cat test2.txt sssshsheeehell[root@master reg]# grep "h$" test2.txt ssssh匹配以 h 结尾的行。\< 或 \b: 锚定词首,用于单词模式左侧,例如:[root@master reg]# cat test2.txt go root userroot:shell;gousershellorootgouser[root@master reg]# grep "\<ro" test2.txt go root userroot:shell;gousers[root@master reg]# grep "\bro" test2.txt go root userroot:shell;gousers可以看到此刻匹配是以单词模式,没有匹配 helloroot。\> 或 \b: 锚定词尾,用于单词模式右侧,例如:[root@master reg]# grep "gouser\b" test2.txt hellorootgouser[root@master reg]# grep "gouser\>" test2.txt hellorootgouser2.2.4 分组引用() 分组:将一个或多个字符当成一个整体来进行后续处理;1…数字引用:从左侧起,引用第一个左括号以及与之匹配右括号之间的模式所匹配到的字符,后向引用,例如:grep -E "(root).*\1" /etc/passwd利用 () 将 root 引用起来,后面利用数字 1 引用。

使用正则表达式进行页面提取

上节课我们学习了如何使用 BeautifulSoup 来解析页面,这节课我们来学习下如何使用正则来解析页面。正则表达式的基本概念正则表达式基本语法正则表达式常用函数通过学习正则表达式几个常用函数,可以根据需要对数据进行匹配筛选。

3. 正则表达式的常用方法

我们开发爬虫使用的是 Python 语言,那么在 Python 中如何使用正则表达式呢?在 Python 中已经内置了正则表达式模块 re,re 库是内置在 Python 中的,不需要我们进行安装,直接导入使用即可。这里我们主要详细讲解一下 re 库中的几种常用方法。这几种方法也是会经常用在爬虫开发中的,只要掌握了这些种方法,基本上在爬虫开发中需要使用正则表达式的问题都可以解决。

4. 常用的正则表达式汇总

正则表达式不一定通用,可能需要结合业务的实际场景来做调整。

1. 正则表达式中的元字符

元字符描述\将下一个字符标记符、或一个向后引用、或一个八进制转义符。例如,“\n”匹配\n。“\n”匹配换行符。序列“\”匹配“\”而“(”则匹配“(”。即相当于多种编程语言中都有的“转义字符”的概念。^匹配输入字行首。如果设置了RegExp对象的Multiline属性,^也匹配“\n”或“\r”之后的位置。$匹配输入行尾。如果设置了RegExp对象的Multiline属性,$也匹配“\n”或“\r”之前的位置。*匹配前面的子表达式任意次。例如,zo*能匹配“z”,也能匹配“zo”以及“zoo”。*等价于{0,}。+匹配前面的子表达式一次或多次(大于等于1次)。例如,“zo+”能匹配“zo”以及“zoo”,但不能匹配“z”。+等价于{1,}。?匹配前面的子表达式零次或一次。例如,“do(es)?”可以匹配“do”或“does”。?等价于{0,1}。{n}n是一个非负整数。匹配确定的n次。例如,“o{2}”不能匹配“Bob”中的“o”,但是能匹配“food”中的两个o。{n,}n是一个非负整数。至少匹配n次。例如,“o{2,}”不能匹配“Bob”中的“o”,但能匹配“foooood”中的所有o。“o{1,}”等价于“o+”。“o{0,}”则等价于“o*”。{n,m}m和n均为非负整数,其中n<=m。最少匹配n次且最多匹配m次。例如,“o{1,3}”将匹配“fooooood”中的前三个o为一组,后三个o为一组。“o{0,1}”等价于“o?”。请注意在逗号和两个数之间不能有空格。?当该字符紧跟在任何一个其他限制符(*,+,?,{n},{n,},{n,m})后面时,匹配模式是非贪婪的。非贪婪模式尽可能少地匹配所搜索的字符串,而默认的贪婪模式则尽可能多地匹配所搜索的字符串。例如,对于字符串“oooo”,“o+”将尽可能多地匹配“o”,得到结果[“oooo”],而“o+?”将尽可能少地匹配“o”,得到结果 [‘o’, ‘o’, ‘o’, ‘o’].匹配除“\n”和"\r"之外的任何单个字符。要匹配包括“\n”和"\r"在内的任何字符,请使用像“[\s\S]”的模式。(pattern)匹配pattern并获取这一匹配。所获取的匹配可以从产生的Matches集合得到,在VBScript中使用SubMatches集合,在JScript中则使用$0…$9属性。要匹配圆括号字符,请使用“\(”或“\)”。(?:pattern)非获取匹配,匹配pattern但不获取匹配结果,不进行存储供以后使用。这在使用或字符来组合一个模式的各个部分时很有用。(?=pattern)非获取匹配,正向肯定预查,在任何匹配pattern的字符串开始处匹配查找字符串,该匹配不需要获取供以后使用。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始。(?!pattern)非获取匹配,正向否定预查,在任何不匹配pattern的字符串开始处匹配查找字符串,该匹配不需要获取供以后使用。例如“Windows(?!95(?<=pattern)非获取匹配,反向肯定预查,与正向肯定预查类似,只是方向相反。*python的正则表达式没有完全按照正则表达式规范实现,所以一些高级特性建议使用其他语言如java、scala等(?<!patte_n)非获取匹配,反向否定预查,与正向否定预查类似,只是方向相反。*python的正则表达式没有完全按照正则表达式规范实现,所以一些高级特性建议使用其他语言如java、scala等[xyz]字符集合。匹配所包含的任意一个字符。例如,“[abc]”可以匹配“plain”中的“a”。[^xyz]负值字符集合。匹配未包含的任意字符。例如,“[^abc]”可以匹配“plain”中的“plin”任一字符。[a-z]字符范围。匹配指定范围内的任意字符。例如,“[a-z]”可以匹配“a”到“z”范围内的任意小写字母字符。注意:只有连字符在字符组内部时,并且出现在两个字符之间时,才能表示字符的范围; 如果出字符组的开头,则只能表示连字符本身.[^a-z]负值字符范围。匹配任何不在指定范围内的任意字符。例如,“[^a-z]”可以匹配任何不在“a”到“z”范围内的任意字符。\b匹配一个单词的边界,也就是指单词和空格间的位置(即正则表达式的“匹配”有两种概念,一种是匹配字符,一种是匹配位置,这里的\b就是匹配位置的)。例如,“er\b”可以匹配“never”中的“er”,但不能匹配“verb”中的“er”;“\b1_”可以匹配“1_23”中的“1_”,但不能匹配“21_3”中的“1_”。\B匹配非单词边界。“er\B”能匹配“verb”中的“er”,但不能匹配“never”中的“er”。\cx匹配由x指明的控制字符。例如,\cM匹配一个Control-M或回车符。x的值必须为A-Z或a-z之一。否则,将c视为一个原义的“c”字符。\d匹配一个数字字符。等价于[0-9]。grep 要加上-P,perl正则支持\D匹配一个非数字字符。等价于[^0-9]。grep要加上-P,perl正则支持\f匹配一个换页符。等价于\x0c和\cL。\n匹配一个换行符。等价于\x0a和\cJ。\r匹配一个回车符。等价于\x0d和\cM。\s匹配任何不可见字符,包括空格、制表符、换页符等等。等价于[ \f\n\r\t\v]。\S匹配任何可见字符。等价于[^ \f\n\r\t\v]。\t匹配一个制表符。等价于\x09和\cI。\v匹配一个垂直制表符。等价于\x0b和\cK。\w匹配包括下划线的任何单词字符。类似但不等价于“[A-Za-z0-9_]”,这里的"单词"字符使用Unicode字符集。\W匹配任何非单词字符。等价于“[^A-Za-z0-9_]”。\xn匹配n,其中n为十六进制转义值。十六进制转义值必须为确定的两个数字长。例如,“\x41”匹配“A”。“\x041”则等价于“\x04&1”。正则表达式中可以使用ASCII编码。\num匹配num,其中num是一个正整数。对所获取的匹配的引用。例如,“(.)\1”匹配两个连续的相同字符。\n标识一个八进制转义值或一个向后引用。如果\n之前至少n个获取的子表达式,则n为向后引用。否则,如果n为八进制数字(0-7),则n为一个八进制转义值。\nm标识一个八进制转义值或一个向后引用。如果\nm之前至少有nm个获得子表达式,则nm为向后引用。如果\nm之前至少有n个获取,则n为一个后跟文字m的向后引用。如果前面的条件都不满足,若n和m均为八进制数字(0-7),则\nm将匹配八进制转义值nm。\nml如果n为八进制数字(0-7),且m和l均为八进制数字(0-7),则匹配八进制转义值nml。\un匹配n,其中n是一个用四个十六进制数字表示的Unicode字符。例如,\u00A9匹配版权符号(©)。\p{P}小写 p 是 property 的意思,表示 Unicode 属性,用于 Unicode 正表达式的前缀。中括号内的“P”表示Unicode 字符集七个字符属性之一:标点字符。其他六个属性:L:字母;M:标记符号(一般不会单独出现);Z:分隔符(比如空格、换行等);S:符号(比如数学符号、货币符号等);N:数字(比如阿拉伯数字、罗马数字等);C:其他字符。*注:此语法部分语言不支持,例:javascript。\< \>匹配词(word)的开始(<)和结束(>)。例如正则表达式<the>能够匹配字符串"for the wise"中的"the",但是不能匹配字符串"otherwise"中的"the"。注意:这个元字符不是所有的软件都支持的。( )将( 和 ) 之间的表达式定义为“组”(group),并且将匹配这个表达式的字符保存到一个临时区域(一个正则表达式中最多可以保存9个),它们可以用 \1 到\9 的符号来引用。

2. 正则表达式基本语法

正则表达式的字符和含义模式描述.匹配任意字符, 除了换行符*匹配前一个字符0次或者多次+匹配前一个字符1次或者多次?匹配前一个字符0次或者1次^匹配字符串开头$匹配字符串结尾()匹配括号内的表达式,表示一个组\s匹配空白字符\S匹配任何空白字符\d匹配数字,等于[0-9]\D匹配非数字,等于[^0-9]\w匹配字符数字,等于[A-Za-z0-9]\W匹配非字符数字,等于[^A-Za-z0-9][]表示一组字符

JavaScript 表达式

表示式亦称表达式、运算式或数学表达式,在数学领域中是一些符号依据上下文的规则,有限而定义良好的组合。数学符号可用于标定数字(常量)、变量、操作、函数、括号、标点符号和分组,帮助确定操作顺序以及有其它考量的逻辑语法。——Wikipedia表达式可以简单理解成一种式子,如 2 + 3 就是一种表达式,通常会叫做算术表达式。通常表达式用来产生值,任何需要用到值的地方都可以放置表达式。一个表达式由操作数与操作符组成,操作数可以由变量、常量或者另一个表达式表示。如:var a = 1;var b = 2;var c = 3;var res = ((a + b) - (c * sqrt(9)));其中第五行等号右边就是一个算术表达式,其由多个算术表达式组成。除了函数调用的括号,剩下所有括号包裹的都是一个表达式。(注意:表达式并不是一定要括号包括,这里是为了方便划分)在等号右侧表达式计算完后,得到一个值,最后会赋值给变量 res,这就是一个赋值表达式。可以见到表达式无处不在。注意:有些文献中会把调用函数描述为一个函数表达式。但通常在JavaScript中会把一种创建函数的方式描述为函数表达式,具体可以查阅函数章节。

Lambda 表达式的设计原则

Java 编程最基本的原则就是要追求高内聚和低耦合的解决方案和代码模块设计,这里我们主要讨论在 Lambda 表达式的环境下来设计我们程序时的两点原则:单一原则 和 开放闭合原则。

1. 为什么要理解表达式

表达式是一个基础而又重要的概念,同时又比较抽象,初学者不好理解。我个人理解的表达式,就是一种具有规则、可以得到一个结果的式子。理解表达式主要是为学习铺路,大量文献中都会用到表达式这个关键词来描述内容。排开这个原因,还有许多表达式是需要单独学习的,如Cron表达式,正则表达式,对表达式的含义有所理解,就很容易接受类似的新名词,理解他们为什么是表达式。

2. Lambda 表达式的作用域规则

匿名内部类与大多数类一样,由于它可以引用从父类继承下来的名字,以及声明在外部类中的名字,所以它的作用域规则非常复杂。Lambda 表达式由于不会从父类型中继承名字,所以它的作用于规则要简单很多。除了参数以外,用在 Lambda 表达式中的名字的含义与表达式外面是一样的。由于 Lambda 表达式的声明就是一个语句块,所以 this 与 super与表达式外围环境的含义一样,换言之它们指向的是外围对象的父类对象。

Kotlin lambda表达式

这篇文章一起来聊下 Kotlin 中的 lambda 表达式。lambda 表达式大家应该都不陌生,这是在 Java8 中引入的一个很重要的特性。将开发者从原来繁琐的语法中解放出来,可是很遗憾的是只有Java8 及以上版本才能使用。而 Kotlin 则弥补了这一问题,Kotlin 中的 lambda 表达式与 Java 混合编程可以支持 Java8以下的版本。那我们带着以下几个问题一起来看下 Kotlin 中 lambda 表达式。

2. Lambda 表达式

在 Java 8 之前,编写一个匿名内部类的代码很冗长、可读性很差,Lambda 表达式的应用则使代码变得更加紧凑,可读性增强;Lambda 表达式使并行操作大集合变得很方便,可以充分发挥多核 CPU 的优势,更易于为多核处理器编写代码。关于 Lambda 表达式我们将在下一小节介绍。

Lambda 表达式

Lambda 表达式是一个 Java 8 以后开始支持的一个非常优雅的新特性,本小节我们将学习什么是 Lambda 表达式,为什么需要 Lambda 表达式,Lambda 表达式的基础语法,以及 Lambda 表达式的实际应用等内容。

2. when 表达式

在 Kotlin 中使用 when 表达式替代了类似 C 语言的 switch-case 语句。其中最简单的形式如下:fun eval(number: Number): String = when (number) { is Int -> "this is int number" is Double -> "this is double number" is Float -> "ths is float number" is Long -> "this is long number" is Byte -> "this is byte number" is Short -> "this is Short number" else -> "invalid number"}//多种条件判断混合形式fun main(args: Array<String>) { println(descript("hello"))}fun descript(obj: Any): String = when (obj) { 1 -> "one" "hello" -> "hello word" is Long -> "long type" !is String -> "is not String" else -> { "unknown type" }}when 将它的参数与所有的分支条件顺序比较,直到某个分支满足条件。 when 既可以被当做表达式使用也可以被当做语句使用。如果它被当做表达式, 符合条件的分支的值就是整个表达式的值,如果当做语句使用, 则忽略个别分支的值。(像 if 一样,每一个分支可以是一个代码块,它的值是块中最后的表达式的值。)Tips:如果其他分支都不满足条件将会求值 else 分支。 如果 when 作为一个表达式使用,则必须有 else 分支, 除非编译器能够检测出所有的可能情况都已经覆盖了。如果很多分支需要用相同的方式处理,则可以把多个分支条件放在一起,用逗号分隔:fun eval(any: Any): String = when (any) { is Int, Double, Float, Long, Byte, Short -> "this is number" //多个分支条件放在一起,用逗号分隔 is Char -> "this is char" else -> "other"}when 也可以用来取代 if-else if 链。 如果不提供参数,所有的分支条件都是简单的布尔表达式,而当一个分支的条件为真时则执行该分支:fun eval(number: Number) { when { number.isOdd() -> { println("this is odd number") } number.isEven() -> { println("this is even number") } else -> println("this is invalid number") }}

首页上一页1234567下一页尾页
直播
查看课程详情
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号