GNU/Linux平台上正则表达式的简单使用
友情提醒:本博文涉及的内容中涉及到的系统实践操作在Centos6.5上实现,GNU/Linux简称为linux,GNU/grep简称为grep,GNU/sed简称为sed,GNU/gawk简称为awk。
-------------------------------------------------楔子---------------------------------------------
小酒馆一角落,一胖三瘦围着方桌坐定,大快耳颐后正在唠嗑。
瘦子甲:“胖子,为什么要把正则表达式和linux联系在一起?”
胖子:“因为下面的内容是在linux平台上正则表达式的简单使用。”
瘦子乙:“你认为linux平台上正则表达式很重要?”
胖子:“重要性无需质疑,linux的两大特性:①一切皆文件。②使用文本文件保存服务配置。就决定了正则表达式和它的三个好×××,grep/sed/awk的组合在处理文件搜索,替换,生成报告文件时,无往而不利。”
瘦子丙:“胖子,你再不开始讲正题,这顿饭你请。”
胖子:“容我在啰嗦一句,linux上正则表达式的使用,是个被写烂的题材,下文若有雷同,纯属巧合,牛人请自闪,约架请先向公安备案。”
----------------------------------正文----------------------------------------------
请先允许我简要介绍下grep这个工具,不然正则表达式没法演示。
1. Grep是个搜索工具,可根据使用者定义的PATTEN,逐行搜索文本或者管道传递的数据,若行中有匹配PATTEN模式的字符串,则该行被打印出来(grep默认行为)。这个PATTEN可以是字符串,或者是使用正则表达式元字符组合的模式。
例如:在/etc/password文件中搜索含有root字符串的行。
[lijun@Test02 test]$ grep --color=auto 'root' /etc/passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
[lijun@Test02 test]$
看是不是很方便的就将含有root字符串的行搜索出来了?!
2.grep的语法格式:
grep [option] 'PATTEN' [FILE...]
常用选项:
--color=auto :使用该选项可使被匹配到的字符串变色显示。
-E:使用扩展的正则表达式。
-o: 只显示匹配模式的字符串,而不显示该行其他的内容。
-v:反向显示,显示那些不含匹配模式字符串的行。
-i:匹配时忽略字符大小写。
-B #:#是数字,显示匹配的行及改行上面的#行。
-C #:#是数字,显示匹配的行及改行上下的#行。
-A #:#是数字,显示匹配的行及改行下面的#行。
*其它的选项请自行使用$man grep 查看。
*模式PATTEN建议使用'' 号或者""号括起来
举例:
生成测试文件及内容:
[lijun@Test02 test]$ cat<<EOF>t1file.txt
> who are you?
> My name is Brad Pitt.
> Your phone number is:135456789
> yes,sir
> EOF
[lijun@Test02 test]$
2.1)显示grep默认行为:搜索含有you字符串的行
[lijun@Test02 test]$ grep 'you' t1file.txt
who are you?
[lijun@Test02 test]$
默认情况下只显示了含有you的行,不含有you字符串的行不显示,且you没有变色。
2.2)实行匹配字符串变色显示:搜索含有you字符串的行
[lijun@Test02 test]$ grep --color=auto 'you' t1file.txt
who are you?
[lijun@Test02 test]$
这下看的可以明显清晰易辨别。
2.3)忽略字符大小写:搜索含有you字符串的行
[lijun@Test02 test]$ grep -i --color=auto 'you' t1file.txt
who are you?
Your phone number is:135456789
[lijun@Test02 test]$
使用选项-i后,搜索范围又一步加大了,You也被匹配到了,同2.2)相比。
2.3)测试-v:搜索不含有you字符串的行
[lijun@Test02 test]$ grep -v -i 'you' t1file.txt
My name is Brad Pitt.
yes,sir
[lijun@Test02 test]$
[lijun@Test02 test]$ grep -v 'you' t1file.txt
My name is Brad Pitt.
Your phone number is:135456789
yes,sir
[lijun@Test02 test]$
为了让看得清使用的选项个数,这里没有将-v和-i合并使用。
2.4)测试下选项 -C#:显示含有name字符串行,及该行上下各1行
[lijun@Test02 test]$ grep -C1 --color=auto 'name' t1file.txt
who are you?
My name is Brad Pitt.
Your phone number is:135456789
[lijun@Test02 test]$
-A#,-B#同-C#使用方式类同,只是显示的行不同,这里就不测试了。
2.5)测试-E选项:含有字符串you或者You的行
[lijun@Test02 test]$ grep -E --color=auto '(y|Y)ou' t1file.txt
who are you?
Your phone number is:135456789
[lijun@Test02 test]$
*看不懂(y|Y),没关系,因为你还没学正则表达式,看完下面的就会了.
3.正则表达式
正则表达式,又称:Regular Expression,RE。计算机科学中的一个概念,它由一堆元字符组成,
再配合人类的思维,可以使用有限的元字符组合,表达一系列符合某些语法模式的字符串,在文本处理
领域中可用来匹配特定模式的字符串,同grep/sed/awk这些工具组合起来使用,可实现文本文件的检索,替换,格式化显示等功能.
在以字符界面为主的linux服务器维护领域,服务的配置是文本文件保存,各种信息的输出都可转变为文本格式出现在维护人员的终端上,例如下面的例子:
例子1)查看22端口是否开启:
[lijun@Test01 ~]$ sudo netstat -tlpn | grep '.*:22'
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1405/sshd
tcp 0 0 :::22 :::* LISTEN 1405/sshd
[lijun@Test01 ~]$
例子2)在/etc/目录下寻找是否有个以udev命名的目录
[lijun@Test01 ~]$ ls -l /etc/ | fgrep 'udev'
drwxr-xr-x. 4 root root 4096 Apr 4 17:01 udev
[lijun@Test01 ~]$
*这比find查找快,比ls /etc 然后一个一个的看更快.
例子3)查看下当前ftp server配置中匿名用户登的权限设定
[lijun@Test01 ~]$ sudo grep --color '^anon' /etc/vsftpd/vsftpd.conf
anonymous_enable=YES
anon_upload_enable=NO
[lijun@Test01 ~]$
例子4)统计并查看当前进程中http server的服务进程:
[lijun@Test01 ~]$ sudo ps -ef |grep 'httpd$'
root 47054 1 0 21:48 ? 00:00:00 /usr/sbin/httpd
apache 47056 47054 0 21:48 ? 00:00:00 /usr/sbin/httpd
apache 47057 47054 0 21:48 ? 00:00:00 /usr/sbin/httpd
apache 47058 47054 0 21:48 ? 00:00:00 /usr/sbin/httpd
apache 47059 47054 0 21:48 ? 00:00:00 /usr/sbin/httpd
apache 47060 47054 0 21:48 ? 00:00:00 /usr/sbin/httpd
apache 47061 47054 0 21:48 ? 00:00:00 /usr/sbin/httpd
apache 47062 47054 0 21:48 ? 00:00:00 /usr/sbin/httpd
apache 47063 47054 0 21:48 ? 00:00:00 /usr/sbin/httpd
[lijun@Test01 ~]$ sudo ps -ef |grep 'httpd$' |wc -l
9
[lijun@Test01 ~]$
这些例子不正是说明正则表达式配合工具文本信息处理方面的强大吗?!
正则表达式分为:基本正则表达式和扩展正则表达式。
基本正则表达式中元字符:
=======匹配字符,数字和符号=========
.:表示任意单个字符
eg:以b开头h结尾中间任意2个字符的,可以表示为'b..h'
[ ]:表示指定范围内的任意单个字符
eg:数字[0-9],小写字母[a-z],大写字母[A-Z]
[^ ]:表示指定范围外的任意单个字符
eg: 非数字的任意字符[^0-9]
[[:digit:]] :0到9数字中任一个,等同于[0-9]
[[:lower:]] :小写字母中任一个,等同于[a-z]
[[:upper:]] :大写字母中任一个,等同于[A-Z]
[[:alpha:]] :大小写字母中任一个,等同于[a-zA-Z]
[[:alnum:]] :字母数字中任一个,等同于[0-9a-zA-Z]
[[:punct:]] :标点符合中任一个
[[:space:]] :任一空白字符
=======匹配字符出现的次数===========
\*:左边的字符出现任意次,和上面的 . 配合使用 .* 可表示任意长度任意字符
\?:左边的字符出现0次或1次
eg:模式 'book\?' 可匹配 'boo' 和 'book'
\+:左边的字符出现至少1次
\{m,n\}:左边的字符出现m到n次
\{m,\}:左边的字符出现至少m次
\{0,n\}:左边的字符出现至多n次
=======锚定位置=======================
^:表示右边的字符出现在行首
eg:以root开头的行 '^root'
$:表示左边的字符出现在行尾
eg:以nologin结尾的行 'nologin$'
\< :表示右边的字符出现在单词首部,可使用\b代替
eg:表示b为词首后跟3个任意字符的词 '\<b...
\> : 表示左边的字符出现在单词尾部,可使用\b代替
\<WORD\>:绝对匹配WORD的单词
eg:匹配单词root \<root\>
========分组与引用====================
\(PATTEN\): PATTEN当作一个整体出现
\(P1\).....\1....:\1的位置出现一个同前边P1一模一样的字符
举例:
3.1)行首匹配符号^:显示/etc/passwd文件中root位于行首的行
[lijun@Test02 test]$ grep --color '^root' /etc/passwd
root:x:0:0:root:/root:/bin/bash
[lijun@Test02 test]$
3.2)行尾匹配符$:显示/etc/passwd文件中bash位于行尾的行
[lijun@Test02 test]$ grep --color 'bash$' /etc/passwd
root:x:0:0:root:/root:/bin/bash
lijun:x:500:500:lijun,115,110,119:/home/lijun:/bin/bash
[lijun@Test02 test]$
3.3)锚定词首符\< 锚定词尾符\> :在/etc/passwd 文件中显示包含以r开头,t结尾,中间2个任意字符的单词的行。
[lijun@Test02 test]$ grep --color=auto '\<r..t\>' /etc/passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
[lijun@Test02 test]$
3.4)显示.与*的组合使用以及贪婪模式: 在/etc/passwd 文件中显示包含以r开头,t结尾,中间任意字符的单词的行。
[lijun@Test02 test]$ grep --color=auto '\<r.*t\>' /etc/passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
[lijun@Test02 test]$
在显示的第一行中匹配那么长,是因为正则表达式的贪婪模式所致。
3.5)范围符号[]的使用:显示/proc/meminfo中以s开头的行
[root@Test02 tt]# grep --color=auto '^[sS]' /proc/meminfo
SwapCached: 0 kB
SwapTotal: 1063928 kB
SwapFree: 1063928 kB
Shmem: 172 kB
Slab: 101220 kB
SReclaimable: 46408 kB
SUnreclaim: 54812 kB
[root@Test02 tt]# grep -i '^s' /proc/meminfo
SwapCached: 0 kB
SwapTotal: 1063928 kB
SwapFree: 1063928 kB
Shmem: 172 kB
Slab: 101228 kB
SReclaimable: 46412 kB
SUnreclaim: 54816 kB
3.6)分组和引用演示:搜索下面文档每行中均有以l开头,e结尾中间任意字符的单词,要求行首同行尾单词相同的行
[root@Test02 tt]# cat 3.txt
she is my love,isn't your love
I like her leg,but she is your love
she is not my love,but her phone as my like
I like dog,but she like cat
[root@Test02 tt]# grep --color '\(\<l..e\>\).*\1' 3.txt
she is my love,isn't your love
I like dog,but she like cat
行中的那些非l开头e结尾的单词被模式 .* 匹配无法除去
扩展的正则表达式:
使用扩展正则表达式使用grep -E 或者 egrep
=======匹配字符,数字和符号=========
与基本正则表达式相同
=======锚定位置=======================
与基本正则表达式相同
=======匹配字符出现的次数===========
*:左边的字符出现任意次
?:左边的字符出现0次或1次
+:左边的字符出现至少1次
{m,n}:左边的字符出现m到n次
{m,}:左边的字符出现至少m次
{0,n}:左边的字符出现至多n次
同基本正则表达式相比不再需要 转义符 \ 转义
========分组与引用====================
(PATTEN): PATTEN当作一个整体出现
(P1).....\1....:\1的位置出现一个同前边P1一模一样的字符
========选择======================
a|b:表示a或者b
例子:
3.7)写个模式匹配下列邮件地址:
[root@Test02 tt]# cat 2.txt
linuxedu@126.com
LINUXEDU@qq.com
171_7717@qq.com
zhijun-L@163.com is j.com
This is my email:zhijun-L@163.com,and this is my http address:http://www.sina.com
[root@Test02 tt]# grep -i -E --color=auto '\<[[:alnum:]]+(-|_){0,}[[:alnum:]]{0,}\>\@\<[[:alnum:]]+\>\.com' 2.txt
linuxedu@126.com
LINUXEDU@qq.com
171_7717@qq.com
zhijun-L@163.com is j.com
This is my email:zhijun-L@163.com,and this is my http address:http://www.sina.com
[root@Test02 tt]#
3.8)写个模式匹配ifconfig eth1中出现的数字:
[root@Test02 tt]# ifconfig eth1|grep --color=auto -E '[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5]'
eth1 Link encap:Ethernet HWaddr 00:0C:29:97:01:8B
inet addr:172.16.200.2 Bcast:172.16.200.255 Mask:255.255.255.0
inet6 addr: fe80::20c:29ff:fe97:18b/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:12535 errors:0 dropped:0 overruns:0 frame:0
TX packets:4685 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:1144613 (1.0 MiB) TX bytes:569776 (556.4 KiB)
[root@Test02 tt]#
3.9)写个模式匹配ifconfig eth1中出现的ip地址和掩码
[root@Test02 tt]# ifconfig eth1|grep --color=auto -E '(\<([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\>\.){3}\<([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\>'
inet addr:172.16.200.2 Bcast:172.16.200.255 Mask:255.255.255.0
好吧,就这些了,上面就是常用到的正则表达式和grep的用法,更详细的请通过书籍,互联网等查询学习。
感谢老婆送的棒棒糖,让我支撑这写完这篇小文。
----------------------------------小结-----------------------------------------------
说完上面这些,胖子瞟了一眼在座的3个同伴,看着他们发发蔫的眼神,胖子心中想到:这比诱惑术还好用?下次大餐时,该多准备些awk,sed配合正则表达式的用法,这样以来就不用自己买单了,嘎嘎。
便向店小二喊道:“座上的3个吃完买单”。变抽身翩然而去。
转载于:https://blog.51cto.com/pirateli/1627333
相关文章:

Linux下addr2line命令用法
Linux下addr2line命令用于将程序指令地址转换为所对应的函数名、以及函数所在的源文件名和行号。当含有调试信息(-g)的执行程序出现crash时(core dumped),可使用addr2line命令快速定位出错的位置。 如果无法确定文件名或函数名,addr2line将在它们的位置打…

JavaMVC 模式
MVC 模式代表 Model-View-Controller(模型-视图-控制器) 模式。这种模式用于应用程序的分层开发。 Model(模型) - 模型代表一个存取数据的对象或 JAVA POJO。它也可以带有逻辑,在数据变化时更新控制器。View࿰…
从概念到技术,打通「中台」的任督二脉,别再说不知道中台是什么
2019 年,「中台」这个词火了!随着阿里等头部互联网企业搭建和推动中台业务,让越来越多的企业关注中台,纷纷提出「中台战略」,帮助企业自身加速实现数字化转型。不少企业还在观望「中台」:1、我的企业里需要…

php中序列化与反序列化
http://www.cnblogs.com/A-Song/archive/2011/12/13/2285619.html 转自:http://qing.weibo.com/tag/unserialize 把复杂的数据类型压缩到一个字符串中 serialize() 把变量和它们的值编码成文本形式unserialize() 恢复原先变量eg:$stooges array(Moe,Larry,Curly);$…

Python3中生成器介绍
生成器(generator):一个返回生成器迭代器的函数。它看起来像一个普通函数,除了它包含用于生成一系列可在for循环中使用的值的yield表达式或者可以使用next函数一次检索一个值。 在Python中,使用了yield的函数被称为生成器。跟普通函数不同的是…
数学学渣必备!拍照上传,分步求解,微软解题神器拯救你
整理 | Jane出品 | AI科技大本营(ID:rgznai100)在学好数学这条路上,很多同志前赴后继「死伤无数」,即便大家不断的寻求「场外救援」,可最终都逃不过一个字:难!两个字:真难…

Java业务代表模式
业务代表模式(Business Delegate Pattern)用于对表示层和业务层解耦。它基本上是用来减少通信或对表示层代码中的业务层代码的远程查询功能。在业务层中我们有以下实体。 客户端(Client) - 表示层代码可以是 JSP、servlet 或 UI j…

在wamp环境下面安装Zend Optimizer的方法
我是用WAMP来做PHP的服务器,进行本机测试和开发PHP项目。 wamp环境是刚刚安装的。由于这个项目的代码是zend加密的,运行时候都是乱码,需要安装一个Zend Optimizer配置。 首先下载一个Zend Optimizer软件。 1、进入安装界面后,按NE…

libuvc介绍及简单使用
libuvc是一个用于USB视频设备的跨平台库,构建在libusb之上,编译libuvc时需要依赖libusb。libuvc的License为BSD,最新发布版本为0.0.6,源码地址: https://github.com/libuvc/libuvc libuvc支持在非windows系统上直接编译࿰…
AI又被彩虹吹!网易被预言为“下一个百度”?
人工智能到底有多火?近日国内首份《BAT人工智能领域人才发展报告》新鲜出炉,此次报告是针对国内人工智能领域的人才争夺情况进行了梳理。并把研究对象锁定在BAT三大巨头的身上。来源:《BAT人工智能领域人才发展报告》其中得出最为核心的结论&…

Java组合实体模式
组合实体模式(Composite Entity Pattern)用在 EJB 持久化机制中。一个组合实体是一个 EJB 实体 bean,代表了对象的图解。当更新一个组合实体时,内部依赖对象 beans 会自动更新,因为它们是由 EJB 实体 bean 管理的。以下…

JAVA的StringBuffer类
StringBuffer类和String一样,也用来代表字符串,只是由于StringBuffer的内部实现方式和String不同,所以StringBuffer在进行字符串处理时,不生成新的对象,在内存使用上要优于String类。 所以在实际使用时,如果…
程序员请收好:10个非常有用的Visual Studio Code插件
作者 | Daan译者 | Elle出品 | CSDN(ID:CSDNnews)【导读】一个插件列表,可以让你的程序员生活变得轻松许多。无论你是经验丰富的开发人员还是刚刚开始第一份工作的初级开发人员,你都会想让自己的开发工作尽可能轻松一点…

Python3中装饰器介绍
Python中的装饰器(decorator)是一个接受另一个函数作为参数的函数。装饰器通常会修改或增强它接受的函数并返回修改后的函数。这意味着当你调用一个装饰函数时,你会得到一个与基本定义相比可能有一些额外特性的函数。Python中的函数可以用作或作为参数传递。 Python…

Java数据访问对象模式
数据访问对象模式(Data Access Object Pattern)或 DAO 模式用于把低级的数据访问 API 或操作从高级的业务服务中分离出来。以下是数据访问对象模式的参与者。 数据访问对象接口(Data Access Object Interface) - 该接口定义了在一…

hdoj 5199 Gunner map
Gunner Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid5199 Description Long long ago, there is a gunner whose name is Jack. He likes to go hunting very much. One day he go to the grove. There are n birds and n tr…

Python3中上下文管理器介绍
在任何编程语言中,文件操作或数据库连接等资源的使用都很常见。但这些资源供应有限。因此,主要问题在于确保在使用后释放这些资源。如果不释放它们,则会导致资源泄漏,并可能导致系统变慢或崩溃。如果用户有一个自动设置和拆卸资源…
LatentFusion:华盛顿大学与英伟达联合提出6D姿态估计新方法
作者 | Keunhong Park、Arsalan Mousavian、Yu Xiang、Dieter Fox 译者 | 刘畅 编辑 | Jane 出品 | AI科技大本营(ID:rgznai100) 【导读】在本文中,华盛顿大学和英伟达联合提出了一种新的用于未见过目标 6D姿态估计的框架。作…

Java前端控制器模式
前端控制器模式(Front Controller Pattern)是用来提供一个集中的请求处理机制,所有的请求都将由一个单一的处理程序处理。该处理程序可以做认证/授权/记录日志,或者跟踪请求,然后把请求传给相应的处理程序。以下是这种…

提供第三种代码生成方式——通过自定义BuildProvider为ASP.NET提供代码生成
2019独角兽企业重金招聘Python工程师标准>>> 之前写了一些关于代码生成的文章,提供了两种不同方式的代码生成解决方案,即CodeDOMCustom Tool和T4。对于ASP.NET应用,你还有第三种选择——自定义BuildProvider。[文中涉及的源代码从…

Java拦截过滤器模式
拦截过滤器模式(Intercepting Filter Pattern)用于对应用程序的请求或响应做一些预处理/后处理。定义过滤器,并在把请求传给实际目标应用程序之前应用在请求上。过滤器可以做认证/授权/记录日志,或者跟踪请求,然后把请…

1200亿次日均位置服务响应、20亿公里日均轨迹里程,百度地图发布新一代人工智能地图生态全景
12月10日,百度地图首次公布了“新一代人工智能地图”生态全景。目前,百度地图日均位置服务请求次数突破1200亿次,日均轨迹里程20亿公里,注册开发者数量达180万,服务超过50万个移动应用。 百度地图事业部总经理李莹称&…

Python3中global/nonlocal用法
全局变量(global variable)是那些未在任何函数内部定义并且具有全局作用域的变量,而局部变量(local variable)是那些在函数内部定义并且其作用域仅限于该函数的变量。换句话说,我们可以说局部变量只能在初始化它的函数内部访问,而全局变量在整…

客户端动态调用WCF服务中的方法
首先要写一个执行动态调用的方法:在里面实现反射调用。 public static object ExecuteMethod<T>(string pUrl,string pMethodName, params object[] pParams) { EndpointAddress address new EndpointAddress(pUrl); Binding bindinginstance null; NetTcpB…

Python3中闭包介绍
Python3中的闭包(closure)是一个函数对象,它记住封闭作用域(enclosing function)中的值,即使它们不存在于内存中。它是一个将函数与环境一起存储的记录。由于闭包用作回调函数,因此它们提供了某种数据隐藏,这有助于我们减少使用全…

Java服务定位器模式
服务定位器模式(Service Locator Pattern)用在我们想使用 JNDI 查询定位各种服务的时候。考虑到为某个服务查找 JNDI 的代价很高,服务定位器模式充分利用了缓存技术。在首次请求某个服务时,服务定位器在 JNDI 中查找服务ÿ…

用AI加速物联网落地,安富利的客户洞察和解决之道
作为一家全球IT解决方案分销商,成立于1921年的安富利也紧随AI浪潮,为区域和全球的终端客户提供AI解决方案。据了解,安富利已为全球超过1400家企业提供技术支持,电子产品年度出货量达1220亿片。 近日在媒体沟通会上,安富…

Linux运维工程师发展前景
随着IT产业的不断发展,尤其是Linux行业的发展,现在互联网企业服务器数量越来越多,当到达几百台,上千台服务器之后,服务器日常管理也逐渐繁杂,每天如果通过人工去频繁的更新或者部署及管理这些服务器&#x…

Python3中__init__.py文件介绍
Python中的模块是包含Python定义和语句的文件(A module is a file containing Python definitions and statements),其文件名是模块名加后缀名.py。在模块内部,通过全局变量__name__可以获取模块名。 模块包含可执行语句及函数定义。这些语句用于初始化模…
赠书 | 熵的实际应用,赌场和金融圈最著名的一个数学公式
本文选自湛庐文化策划出版图书《模型思维》。作者斯科特佩奇,超过100万用户的“模型思维课”主讲人。密歇根大学复杂性研究中心“掌门人”。圣塔菲研究所外聘研究员。曾出版《多样性红利》一书。斯科特佩奇以对社会科学多样性和复杂性的研究和建模面闻名。具体研究方…