1. 正则表达式及其应用
正则表达式(英语:Regular Expression,常简写为regex、regexp或RE),又称正则表示式、正则表示法、规则表达式、常规表示法。正则表达式使用单个字符串来描述、匹配一系列符合某个句法规则的字符串。在很多文本编辑器里,正则表达式通常被用来检索、替换那些符合某个模式的文本。
Linux中很多命令都支持正则表达式,比如接下来要提到的grep命令,而接下来我们要讲的内容也将以grep命令结合正则表达式,来充分介绍一些常用的用法。
正则表达式有两种:标准正则表达式和扩展正则表达式。
正则表达式的元字符从功能上可以分为以下四类:字符匹配,次数匹配,位置锚点,分组和逻辑组合。以下也将逐一介绍。
补充:
许多程序设计语言都支持利用正则表达式进行字符串操作。例如,在Perl中就内建了一个功能强大的正则表达式引擎。正则表达式这个概念最初是由Unix中的工具软件(例如sed和grep)普及开的。
最初的正则表达式出现于理论计算机科学的自动控制理论和形式化语言理论中。在这些领域中有对计算(自动控制)的模型和对形式化语言描述与分类的研究。
1940年,沃伦·麦卡洛克与Walter Pitts将神经系统中的神经元描述成小而简单的自动控制元。
1950年代,数学家斯蒂芬·科尔·克莱尼利用称之为“正则集合”的数学符号来描述此模型。肯·汤普逊将此符号系统引入编辑器QED,随后是Unix上的编辑器ed,并最终引入grep。自此以后,正则表达式被广泛地应用于各种Unix或类Unix系统的工具中。正则表达式的POSIX规范,分为基本型正则表达式(Basic Regular Expression,BRE)和扩展型正则表达式(Extended Regular Express,ERE)两大流派。在兼容POSIX的UNIX系统上,grep和egrep之类的工具都遵循POSIX规范,一些数据库系统中的正则表达式也符合POSIX规范。grep、vi、sed都属于BRE,是历史最早的正则表达式,因此元字符必须转译之后才具有特殊含义。egrep、awk则属于ERE,元字符不用转译。
补充2:
1.1 正则表达式中字符匹配
1.1.1 匹配任意字符
.
可以匹配任意的单个字符、英文字母、数字,以及他本身。
.
可以连续使用,比如我们可以写出..m..
这样一个正则表达式,他将匹配所有:前面有任意两个字符,后面紧跟着一个m,又随后跟着任意两个字符的文本。
1.1.2 匹配.
元字符怎么办?
有时候我不想让.
去匹配任意字符,只想匹配自身就好,该怎么办呢?
此时,可以使用\.
来对其进行转义。
例如:\.com
会匹配.com,而不会匹配1com、2com
补充:
如果要匹配
\
可以使用\\
来对其进行转义
1.2 匹配字符组
我们了解.
可以匹配几乎所有的单个字符,但有的时候我们只想要匹配几个有限字符中的某一个,就无需用到它了,这时候我们可以使用字符组来匹配。
假设有这样一种情况,我们希望匹配两个单词,比如hero和here,即her后面要么出现o要么出现e,其他的情况都不需要,那该怎么办呢?
正则表达式提供了字符组来解决这个问题,当遇到这重her后面只想匹配o或者e的情况,它的语法是[oe]
,[]
中括号是特殊标记,可以划定属于组内的字符的界定。因此[oe]
所代表的含义是:“匹配e或者o” 。
补充:
字符组虽然由多个字符构成,但对于正则表达式来说,他只匹配“单个”字符,而字符组能够匹配的单个字符,即是他定义中的字符(
[]
内的字符)。[]
本身不进行字符匹配,他仅仅划定字符组的边界。
1.2.1 字符组中的字符区间
假设我们要匹配一组文件,其命名方式为:a1,a2,a3…a9,根据前面介绍的方式,我们可以写出a[123456789]
这样的正则表达式,这样确实能够达到我们想要的结果,但如果需要匹配的范围在大点呢,比如:a1,b1,c1…z1,我们如果把26个英文字母塞进正则表达式中就太麻烦了,有没有更好的方法呢?
毫无疑问,正则表达式提供了字符区来简化这一过程,他的语法是起始字符-结束字符对于上面的例子,我们可以用[1-9]和[a-z]
来解决。
补充:
如果要在
[]
中匹配-
需要用到转义字符\-
而在[]
以外,-
变成了一个普通字符,无需在进行转义。
1.2.2 反义字符组
有时候我们需要匹配一些“除某些字符以外”的其他字符,这时候,我们可以使用反义字符,他的用法是[^字符合集]
以上面的例子为例,我们只想匹配除:a1,a2,a3以外的文件,这时我们可以这样写正则表达式:a[^1-3]
1.3 匹配多个字符
上面的知识中,我们可以知道,无论简单也好,复杂也好,他们都只是匹配单个字符,如果要匹配多个字符,而组成这个字符串的每个字符都比较复杂的情况下,我们该如何让我们的正则表达式正确的发挥作用?
1.3.1 匹配一个或多个
正则表达式中,可以在单个字符、字符组、特定字符类型、单个任意字符后面加一个+
来匹配一个或多个字符组成的字符串
1.3.2 一些有用的元字符
. |
代表任意单个字符 |
---|---|
[] |
指定范围内的字符,[hero] 表示h,e,r,o这4个字母 |
[^] |
排除[] 中字符以外的字符,[^hero] 表示除h,e,r,o这4个字母 |
[:alnum:] |
代表大小写字母和数字 |
[:alpha:] |
代表大小写字母 |
[:lower:] |
代表小写字母 |
[:blank:] |
代表空格和TAB |
[:digit:] |
所有单个空字符 |
[:graph:] |
所有单个非空字符 |
[:print:] |
代表可打印的字符 |
[:punct:] |
代表标点符号 |
1.3.3 正则表达式中的次数匹配
在处理文本时,有时候需要指定某个内容出现的具体次数,这时候就要用到一些特殊的元字符
* |
代表匹配*前面的字符出现了任意次,也可以是0次 |
---|---|
\? |
代表匹配其前面的字符1次或者0次 |
\+ |
代表匹配其前面的字符大于等于1次 |
\{n\} |
代表匹配其前面的字符连续出现n次,n是数字 |
\{m,n\} |
代表匹配其前面的字符次数要大于等于m,小于n次 |
\{m,\} |
代表匹配其前面的字符次数最少出现m次 |
\{,n\} |
代表匹配其前面的字符小于等于n次 |
1.3.4 正则表达式的位置锚点
对文本处理时,常想表示指定字符出现的位置,比如行首,行尾,词首,词尾等。那么以下的元字符可以帮到你。
^ |
行首锚定 |
---|---|
$ |
行尾锚定 |
^PATTERN$ |
精确匹配整行 |
^$ |
空行 |
^[[:space:]]*$ |
空白行 |
\< 或 \b |
词首锚点 |
\> 或 \b |
词尾锚点 |
\<PATTERN\> |
匹配整个单词 |
1.3.5 扩展正则表达式的使用
普通的正则表达式不错是不错,就是转义符要输入太多了,看起来不是非常美观,所以,才有了扩展的正则表达式,能够让表达式看起来更直观一些;
? |
代表匹配1次或者多次 |
---|---|
+ |
代表匹配1次或0次 |
{m} |
代表匹配m次 |
{m,n} |
代表最少匹配m次最多匹配n次 |
() |
分组符号 |
| |
或逻辑符号 |
grep -E |
实现支持扩展正则表达式 |
2. Linux用户和组的权限管理
linux是一个多用户的操作系统,即同一个时间允许多个用户同时使用。为了实现不同的用户可以设置不同的权限,需要针对每个不同的权限的用户创建对应的用户账号,而为了管理起来更加方便,可用将用户加入到组中。此外用户必须要有一个组,此组成为用户的主组,用户也可以再加入到其他组中,此组称为附属组或附加组。
2.1 查看用户信息文件
Linux系统中每个用户都有一个唯一的用户编号与其对应,我们将其称为UID(User IDentifier)在Linux中区分不同的用户就是通过UID来实现的,而非我们习惯以为的用户名。每个登录用户的基本信息保存在/etc/passwd
中,每一行都存放了对应的用户信息。
[root@localhost ~]# cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
...
我们拿出第一行来说说吧:
root:x:0:0:root:/root:/bin/bash
通过冒号分开的内容分别为:
root |
用户名 |
---|---|
x |
早期时这个位置是存放密码的,后来基于安全考虑,密码转移至/etc/shadow 中了 |
0 |
表示用户编号,UID,此处的0代表为超级用户 |
0 |
此处表示组编号,GID |
root |
此处是用户的说明信息位置 |
/root |
表示此用户的家目录位置 |
/bin/bash |
表示此用户的默认shell类型 |
3. 一些用户管理的常用命令
groupadd
语法
groupadd
命令 语法格式如下:
groupadd [-g gid [-o]] [-r] [-f] group
参数说明:
- -g:指定新建工作组的 id;
- -r:创建系统工作组,系统工作组的组ID小于 500;
- -K:覆盖配置文件 “/ect/login.defs”;
- -o:允许添加组 ID 号不唯一的工作组。
- -f,–force: 如果指定的组已经存在,此选项将失明了仅以成功状态退出。当与 -g 一起使用,并且指定的GID_MIN已经存在时,选择另一个唯一的GID(即-g关闭)。
useradd
语法
useradd [-mMnr][-c <备注>][-d <登入目录>][-e <有效期限>][-f <缓冲天数>][-g <群组>][-G <群组>][-s <shell>][-u <uid>][用户帐号]
或
useradd -D [-b][-e <有效期限>][-f <缓冲天数>][-g <群组>][-G <群组>][-s <shell>]
参数说明:
-
-c<备注> 加上备注文字。备注文字会保存在passwd的备注栏位中。
-
-d<登入目录> 指定用户登入时的起始目录。
-
-D 变更预设值.
-
-e<有效期限> 指定帐号的有效期限。
-
-f<缓冲天数> 指定在密码过期后多少天即关闭该帐号。
-
-g<群组> 指定用户所属的群组。
-
-G<群组> 指定用户所属的附加群组。
-
-m 自动建立用户的登入目录。
-
-M 不要自动建立用户的登入目录。
-
-n 取消建立以用户名称为名的群组.
-
-r 建立系统帐号。
-
-s 指定用户登入后所使用的shell。
-
-u 指定用户ID。
userdel
语法
userdel [-r][用户帐号]
参数说明:
- -r 删除用户登入目录以及目录中所有文件。
usermod
语法
usermod [-LU][-c <备注>][-d <登入目录>][-e <有效期限>][-f <缓冲天数>][-g <群组>][-G <群组>][-l <帐号名称>][-s <shell>][-u <uid>][用户帐号]
参数说明:
- -c<备注> 修改用户帐号的备注文字。
- -d登入目录> 修改用户登入时的目录。
- -e<有效期限> 修改帐号的有效期限。
- -f<缓冲天数> 修改在密码过期后多少天即关闭该帐号。
- -g<群组> 修改用户所属的群组。
- -G<群组> 修改用户所属的附加群组。
- -l<帐号名称> 修改用户帐号名称。
- -L 锁定用户密码,使密码无效。
- -s 修改用户登入后所使用的shell。
- -u 修改用户ID。
- -U 解除密码锁定。
4. 一些练习
1、显示/etc目录下,以非字母开头,后面跟了一个字母以及其它任意长度任意字符的文件或目录
ls -d /etc/[^[:alpha:]][[:alpha:]]*
2、复制/etc目录下所有以p开头,以非数字结尾的文件或目录到/tmp/mytest1目录中。
#分析:本题有两个需求,一个是要有一个目录/tmp/mytest1,一个是复制/etc下所有p开头的且以非数字结尾的文件,匹配的正则表达式为:p*[^[:digit:]]
mkdir /tmp/mytest1
cp -r /etc/p*[^[:digit:]] /tmp/mytest1/
#也可以组合一下
mkdir /tmp/mytest1 && cp -r /etc/p*[^[:digit:]] /tmp/mytest1/
3、将/etc/issue文件中的内容转换为大写后保存至/tmp/issue.out文件中
#分析:将大象放进冰箱要几步?
#分析:1.先把/etc/issue文件内容提取出来,2.转成大写,3.写入/tmp/issue.out中
cat /etc/issue |tr 'a-z' 'A-Z' > /tmp/issue.out
#知识点:cat、tr、|、>
4、请总结描述用户和组管理类命令的使用方法并完成以下练习:
(1)、创建组distro,其GID为2019;
#知识点:groupadd
groupadd distro -g 2019
(2)、创建用户mandriva, 其ID号为1005;基本组为distro;
#知识点:useradd
useradd mandriva -u 1005 -g distro
(3)、创建用户mageia,其ID号为1100,家目录为/home/linux
#知识点:useradd
useradd mageia -u 1100 -d /home/linux
(4)、给用户mageia添加密码,密码为mageedu,并设置用户密码7天后过期
#知识点:passwd
echo "mageedu" |passwd -x 7 --stdin mageia
彩蛋:mageia
Mageia 是一个非营利组织及其主导的Linux发行版的名称。
Mageia是Mandriva Linux于2010年9月形成的分支,它由那份来自法国的颇受欢迎的Linux发行的前雇员及贡献者们创建。与Mandriva这份商业实体所不同的是,Mageia计划乃是一个社区项目及一个非盈利性组织,它的目标是开发一套自由的基于Linux的操作系统
“Mageia”一词出自希腊语“μαγεία”,在英语中对应为"magic",即“魔术”。之所以取这一名称,灵感来自魔术师 Leon Mandrake 的名字,而 Mandrake 也是 Mandriva Linux 发行版的原名。
(5)、删除mandriva,但保留其家目录;
#知识点:userdel
userdel mandriva
#userdel默认不删除家目录
彩蛋:mandriva
Mandriva S.A. 是一间法国的软件公司,企业总部位于巴黎,研发总部位于巴西库里奇巴。他们创造了Mandriva Linux,并负责维持与研发。
它的前身是创建于1998年的MandrakeSoft。
(6)、创建用户slackware,其ID号为2002,基本组为distro,附加组peguin;
#知识点:group useradd
#首先要创建一个组:peguin
groupadd peguin
#创建用户指定ID 基本组 附加组
useradd -u 2002 -g distro -G peguin slackware
彩蛋:slackware
Slackware是Slackware Linux, Inc的[Patrick Volkerding](http://en.wikipedia.org/wiki/Patrick Volkerding)制作的Linux发行版本。Slackware走了一条与其他的发行版本(Red Hat、Debian、Gentoo、SuSE、Mandriva、Ubuntu等)不同的道路,它力图成为“UNIX风格”的Linux发行版本。它的方针是只吸收稳定版本的应用进程,并且缺少其他Linux版本中那些为发行版本定制的配置工具。
(7)、修改slackware的默认shell为/bin/tcsh;
#知识点:usermod
usermod -s /bin/tcsh slackware
(8)、为用户slackware新增附加组admins;
#知识点:groupadd usermod
groupadd admins
usermod -G admins slackware