文本主要介绍正则表达式、grep家族命令,以及vim与文件查找工具,如find与locate。
正则表达式(REGular EXPression,REGEXP)使用单个字符串来描述、匹配一系列匹配某个句法规则的字符串的机制。它将一些字符作为元字符(Meta Characteristic) 用于标识一类字符或用于特殊限定,而不是标识其原有的字面意义。
在进行文本匹配时,我们所写的匹配表达式被称为模式(Pattern) ,而在Linux中,最常用的支持正则表达式的程序为grep家族程序,根据其划分,又分为:
在介绍正则表达式之前,前介绍grep的用法
这三个命令类似,都用作文本过滤,grep(Global Search Regular EXpression and print out the line)默认使用BRE,egrep默认使用ERE,fgrep模式不支持REGEXP,f为fast之意。
由于以上三个命令可以使用参数而达到与彼此相同的效果,故而此处以grep为例进行说明,其用法如下:
grep [OPTIONS] PATTERN [FILE...]
[OPTIONS]
-i ignore-case 忽略大小写
--colour=auto
将匹配到的字符高亮显示,默认命令别名开启
-v 反向匹配,显示没有被模式匹配到的行
-o 只显示被模式匹配到的字符串,而非整行
-q 静默模式,不输出任何信息
-E 支持扩展的正则表达式(egrep)
-F 支持快速匹配(fgrep)
-A # After,显示被模式匹配到的后面的#行
-B # Before,显示被模式匹配到的前面的#行
-C # Context,显示被模式匹配到的前#行与后#行
-P 使用perl风格的正则表达式
PATTERN
模式,即用于匹配的条件,将在下面介绍
通配符 | 意义 |
---|---|
* | 任意长度的任意字符 |
? | 任意单个字符 |
[] | 指定范围内的任意单个字符 |
[^] | 指定范围外的任意单个字符 |
正则表达式的介绍主要内容为介绍其元字符,分为以下几类:
元字符 | 意义 |
---|---|
. | 匹配任意字符 |
[] | 匹配指定范围内的字符 |
[^] | 匹配指定范围外的字符 |
注意,这里只是确定匹配什么字符,匹配次数并不由此限制。
关于范围,可使用如下方式表示:
范围 | 意义 |
---|---|
[0-9],[[:digit:] | 数字 |
[a-z],[[:lower:]] | 小写字母 |
[A-Z],[[:upper:]] | 大写字母 |
[[:punct:]] | 标点符号 |
[[:space:]] | 空白符号 |
[[:alpha:]] | 所有字母(大写与小写) |
[[:alnum:]] | 字母与数字 |
以上两个中括号的意义为,外层标识正则表达式的范围,内层与其中的内容共同标识一个集合,若要匹配外围以外的,组在两个中括号之间加上^即可,如:
[^[:lower:]]
:非小写字母
用在要指定其出现的次数的字符的后面,用于限定其前面字符出现的次数
元字符 | 意义 |
---|---|
* | 匹配其前面字符任意次(0次,1次,或多次) |
\? | 0次或1次 |
\+ | 1次或多次 |
\{m\} | m次 |
\{m,n\} | 至少m次,至多n次 |
这里需要使用转义,因为BRE将+、?、{、}等字符默认是作为字字面意义进行匹配的,这里需要使其作为元字符使用。
另外,关于次数匹配也有以下用法:
次数表示 | 意义 |
---|---|
.* | 任意长度的任意字符 |
\{0,n\} | 至多n次 |
\{m,\} | 至少m次 |
试想若有如下内容的文本:
one two one three one
使用以下命令进行匹配:
grep -o "one.*one" test.grep
得到的结果为:
one two one three one
而事实上“one two one”也是满足模式的,这里之所以是如此结果,是因为grep默认工作在 贪婪模式 下,这意味着grep会尽可能长地匹配字符。
若要尽可能短地匹配,则需要其在非贪婪模式下匹配,而grep与egrep默认是不支持这种模式的。
我们可以使用-P选项,以为使用Perl语言风格的正则表达式进行模式匹配,号称Perl的正则表达式引擎是非常强大的。
Perl风格中,在次数限定元字符后加 ? 可使其工作在非贪婪模式下,如:
grep -o -P "one.*?one" test.grep
结果为
one two one
元字符 | 意义 |
---|---|
^ | 锚定行首 |
$ | 锚定行尾 |
\<或\b | 锚定词首,用于单词左侧 |
\>或\b | 锚定词尾,用于单词右侧 |
常见用法
模式 | 意义 |
---|---|
\ |
匹配完整单词 |
^PATTERN$ | 用PATTERN匹配整行 |
^$ | 空白行 |
^[[:space:]]*$ | 空行或包含空白字符的行 |
有时需要将一个组合作为一个单位进行限定,如要匹配出现多个连续的“ab”,此时可使用分组
分组是使用小括号实现的,不过在BRE中需要转义,如以上要求的模式应写为\(ab\)*
分组的另一个作用为,可再次引用匹配到的内容(后向引用),如若使用r..t
匹配到了“root”,则在下次引用时,引用的占位符将被替换为“root”。
分组括号中的模式匹配到的内容会被正则表达式引擎记录于内部变量中,这些变量的命名方式为\1,\2,\3,……
如,有以下文本内容:
He likes his lover.
She loves her liker.
He loves his lover.
She likes her liker.
grep '\(l..e\).*\1r'
将会匹配到:
He loves his lover.
She likes her liker.
grep -i '^s' /proc/meminfo
grep '^[sS]' /proc/meminfo
grep 'nologin$' /etc/passwd
grep "nologin$' /etc/passwd | cut -d: -f1
grep 'bash$' /etc/passwd | sort -n -t: -k3 | head -1 | cut -d: -f1
grep "^#[[:space:]]\{1,\}[^[:space:]]" /etc/inittab
grep ':[0-9]:' /etc/inittab
grep '^[[:space:]]\{1,\}' /boot/grub/grub.conf
grep '^\([0-9]\).*\1$' /etc/inittab
netstat -tan | grep "LISTEN[[:space:]]*$"
ERE与BRE类似,只是将更多的字符纳入了元字符,如此在使用时将不必转义,其他与BRE类似,与这里做如下总结
元字符 | 意义 |
---|---|
. | 匹配任意字符 |
[] | 匹配指定范围内的字符 |
[^] | 匹配指定范围外的字符 |
元字符 | 意义 |
---|---|
* | 匹配其前面字符任意次(0次,1次,或多次) |
? | 0次或1次 |
+ | 1次或多次 |
{m} | m次 |
{m,n} | 至少m次,至多n次 |
元字符 | 意义 |
---|---|
^ | 锚定行首 |
$ | 锚定行尾 |
\<或\b | 锚定词首,用于单词左侧 |
\>或\b | 锚定词尾,用于单词右侧 |
元字符 | 意义 |
---|---|
() | 分组 |
\1, \2, \3, … | 后向引用 |
元字符 | 意义 |
---|---|
| | 表示“或者”之意 |
该元字符在BRE中并未出现,这里需要说明的是,|匹配的是真个左边或整个右边,而不是单个字符,如:
c|Cat
可以匹配的是c与Cat,而非cat与Cat,若要用C|cat
表示C|c
可以使用()
分组:(C|c)at
同nano一样,vim也是一款全屏幕的编辑器,他是vi(visual Interface)编辑器的进化版(improved),功能异常强大。
vim是一个模式化的编辑器,这里介绍常用几种模式
vim [OPTIONS] /PATH/TO/SOMEFILE...
OPTIONS
-o 水平分割显示
-O 垂直分割显示
Ctrl+w,箭头 窗口间跳转
若打开单个文件,这里将不会分隔窗口
+N 打开文件并定位在第N行的行首
+/PATTERN 打开文件后,直接让光标处于第一个被PATTERN匹配到的行的行首
+ 打开文件并定位在最后一行
通配符 | 意义 |
---|---|
. | 当前行 |
$ | 最后一行 |
$-1 | 倒数第二行 |
+# | 向下的#行 |
按键 | 动作 |
---|---|
h或← | 向左 |
l或→ | 向右 |
j或↓ | 向下 |
k或↑ | 向上 |
按键 | 动作 |
---|---|
w | 移至下一个单词的词首 |
b | 调至当前或前一个单词词首 |
e | 跳至当前或下一个单词词尾 |
#COMMAND:可以移动#个单词
按键 | 动作 |
---|---|
0 | 数字0,跳至绝对行首 |
^ | 跳至行首的第一个非空白字符 |
$ | 跳至绝对行尾 |
按键 | 动作 |
---|---|
#G | 跳转至第#行 |
G | 跳转至最后一行 |
1G或gg | 跳转至第一行 |
按键 | 动作 |
---|---|
) | 下一句 |
( | 上一句 |
按键 | 动作 |
---|---|
} | 下一段 |
{ | 上一段 |
按键 | 动作 |
---|---|
Ctrl+f | 向文件尾部翻一屏 |
Ctrl+b | 向文件首部翻一屏 |
Ctrl+d | 向文件尾部翻半屏 |
Ctrl+u | 向文件首部翻半屏 |
Enter | 按行向后翻 |
按键 | 动作 |
---|---|
x | 删除光标所在处的单个字符 |
#x | 删除光标所在处及向后的共#个字符 |
d命令跟跳转命令组合使用,用于删除光标当前位置到跳转到位置的字符,#d跳转符:如:
按键 | 动作 |
---|---|
3dw | 删除光标向后的3个单词 |
d^ | 删除至行首 |
d$ | 删除至行尾 |
dd | 删除当前光标所在行 |
#dd | 删除包括当前光标所在行在内的下#行 |
即先删除内容,再转换为输入模式,用法同d命令,如
按键 | 动作 |
---|---|
c$ | 删除光标值行尾内容并转为输入模式 |
c^ | 删除光标值行首内容并转为输入模式 |
cc | 删除光标所在行内容并转为输入模式 |
#cc | 删除包括当前光标所在行在内的下#行并转为输入模式 |
使用方法同删除命令,如
按键 | 动作 |
---|---|
c$ | 复制光标值行尾内容 |
c^ | 复制光标值行首内容 |
cc | 复制光标所在行内容 |
#cc | 复制包括当前光标所在行在内的下#行 |
vim中编辑的内容可以撤销,最后一次删除的内容会被保存至内存的缓冲区中,可以用于下次粘贴至他处,相当于剪切
先按r,再按下字符,可以将当前光标所在的字符替换的键入的字符
#r:向后替换#个字符
可敲R进入替换模式,替换模式下键入的字符将直接替换原字符
按键 | 动作 |
---|---|
u | 撤销前一次的编辑操作 |
#u | 撤消指定次数的操作 |
U | 仅撤销光标所在行的编辑操作 |
Ctrl+r | 还原撤销 |
连续u命令可撤消此前的n次编辑操作,默认最多撤销50次操作
在编辑模式中,使用.可重复之前的操作
按键 | 动作 |
---|---|
Ctrl+w, s | 水平拆分窗口 |
Ctrl+w, v | 垂直拆分窗口 |
在窗口键切换的方式为:Ctrl+w,箭头
ZZ (大写)保存并退出
该模式可以选中光标划过的所有字符
按键 | 动作 |
---|---|
v | 按字符选取 |
V | 按行选取 |
经常结合编辑命令:d,c,y
按键 | 动作 |
---|---|
:e FILE | 打开新文件 |
:r FILE | 读取其他文件至当前文件 |
按键 | 动作 |
---|---|
:q | 不保存退出(若修改了文件内容则无法退出) |
:wq | 保存并退出 |
:x | 同: wq ,保存并退出 |
:q! | 强行不保存退出 |
:w | 保存(只读属性的文件无法保存) |
:w /PATH/TO/SOMEFILE | 另存为 |
:w! | 强行保存(管理员) |
qall | 退出所有文件 |
wall | 保存所有文件 |
直接给出行号,回车即可
使用地址定界的形式为:START,END
,如
定界操作 | 意义 |
---|---|
# | 第#行 |
m,n | 第m行到第n行 |
m,+n | 相对定界,从第m行开始,往后n行 |
. | 当前行 |
$ | 最后一行 |
$-2 | 倒数第3行 |
/PAT1/,/PAT2/ | 自光标处开始匹配,从第一次能够被模式一(PAT1)匹配到的行开始,到以第一次能够被模式二(PAT2)匹配到的行结束,中间的所有行,通常的使用形式为/PAT/,$ |
% | 全文,相当于1,$ |
末行模式中的编辑操作格式为:地址定界后跟一个编辑命令,可实现对范围内的内容进行相应的编辑操作。如:
指令 | 操作 |
---|---|
#d | 删除光标所在行与向下的行供#行 |
%y | 复制全部内容 |
m,nw /PATH/TO/SOMEWHERE | 将m行到n行的内容写入指定文件中 |
m,nr /PATH/FROM/SOMEFILE | 将m至n行的内容替换为指定文件中的内容 |
指令 | 操作 |
---|---|
/PATTERN | 从当前光标向尾部查找 |
?PATTERN | 从当前光标向首部查找 |
n | 与命令同方向 |
N | 与命令反方向 |
在末行模式下使用s命令,用法同sed中的s命令1
s命令默认只替换每行中第一次被模式匹配到的字符串,其使用格式为:
:地址定界s/查找模式/替换为的内容/修饰符
修饰符 | 意义 |
---|---|
g | global,全局替换,替换(一行中)所有被模式匹配到的字符串,默认只替换每一行的第一个 |
i | ignore-case,忽略字符大小写 |
如:
删除全文的行首的#
:%s@^#@@g
将1到30行行首是非#的行加上#
:1,30s@^[^#]@#&@g
将行首的空白字符替换为空
:%s/^[[:space:]]\+//
将每行开头为空白符的行首加一个#
:%s/^[[:space:]]/#&/
按键 | 动作 |
---|---|
:sp [FILE] | 水平分割显示 |
:vsp [FILE] | 垂直分割显示 |
当使用vim同时打开多个文件而没有指定分屏时,默认是将第一个文件全屏显示的,此时可以通过如下方式在打开的文件之间切换:
指令 | 操作 |
---|---|
: next | 切换至下一个文件 |
: previous | 切换至前一个文件 |
: last | 切换至最后一个文件 |
: first | 切换至第一个文件 |
即在vim中执行shell命令,在末行模式下输入!,后跟命令即可。
若在vim中编辑了内容,在未保存的情况下意外关闭,在下次编辑时vim将会警告,可以使用vim -r 恢复未保存的数据,删除同目录下的*.swp文件,亦可在警告窗口中根据提示进行操作
在末行模式下使用set
可设定相关参数,用于修改vim的当前配置,不带任何参数的set
命令可查看set的帮助
: set number 显示行号
: set nu
: set nonumber 取消显示
: set nonu
: set ignorecase 忽略大小写
: set ic
: set noic 区分大小写
: set autoindent 自动缩进
: set ai
: set autoindent 取消缩进
: set noai
: sethlsearch 高亮显示搜索到的文本
: set nohlsearch 取消高亮显示搜索到的文本
: nohl 取消高亮显示搜索到的文本
: syntax on 开启语法着色
: syntax off 关闭语法着色
:setshowmatch 显示与之匹配的括号
:set sm
:setshowmatch 取消显示
:set nosm
该操作可立即生效,作用域仅为当前vim进程
vim有两种配置文件
通过将以上属性设置指令写入配置文件,可永久生效
vim是一个很复杂的工具,这里介绍的只是基础用法,关于帮助的获取,可使用如下方式:
另外,vimtutor
命令中有关于vim的相关教程
前文介绍的grep家族工具用作文本过滤,他们作用于文件时,是过滤文件内容,而此处介绍的文件查找工具,将通过特定条件,查找文件本身。
该命令将通过文件名查找文件,基本使用格式为:
locate [OPTION]... PATTERN…
[OPTION]
-b:只匹配基名
-c:统计出共有多少个符合条件的文件
-r:基于BRE(基本正则表达式)搜索
需要说明的是,find的查找是根据全系统数据库进行的,系统将在任务计划的配置下,在设定时间将系统上的文件信息收集到全系统数据库中,locate将在这个数据库中进行查找,速度较快,但由于是基于该索引,故其结果并非实时。
如当前新建了一个文件,呃索引数据尚未建立该条目,则locate将无法找到该文件,欲手动生成文件数据库,可使用updatedb
命令构建索引
注意,索引构建过程需要遍历整个根文件系统,极其消耗资源
与locate不同,find命令将做实时查找,并且支持众多查找标准,因而其速度较find慢
其使用格式为:
find [option] … [查找路径] [查找条件] [处理操作]
查找路径:指定具体目标路径,默认为当前目录
查找条件:可以是文件名、大小、类型、权限等标准,默认为指定路径下的所有文件,即无条件
处理操作:对符合条件的文件做什么操作,默认为输出至屏幕
以下将对其做详细说明
-name 'FILENAME' 对文件名做精确匹配,区分大小写
文件名通配
* 任意长度的任意字符
? 任意单个字符
[] 指定范围内的
[^] 指定范围外的
-iname 'FILENAME' 文件名匹配不区分大小写
-regex 'PATTERN' 基于正则表达式进行文件名匹配
以PATTERN匹配整个文件路径字符串,而不仅仅是文件名
-user USERNAME 根据属主查找
-group GRPNAME 根据属组查找
-uid UID 根据UID查找
-gid GID 根据GID查找
若一个文件的属主用户被删除,则该文件的属主将变为删除用户的UID,此时,该文件没有属主,属组亦然
-nouser 查找没有属主的文件
-nogroup 查找没有属组的文件
-typeTYPE 根据文件类型查找
f 普通文件
d 目录
c 字符设备文件
b 块设备文件
l 符号链接文件
p 命名管道
s 套接字文件
-size[+|-]UNIT
指定查找大小,后跟数字和单位(UNIT),若没给出单位,则为默认的“字节”,+和-表示至少、至多
关于单位,可指定为:
单位 | 意义 |
---|---|
b | for 512-byte blocks (this is the default if no suffix is used) |
c | for bytes |
w | for two-byte words |
k | for Kilobytes (units of 1024 bytes) |
M | for Megabytes (units of 1048576 bytes) |
G | for Gigabytes (units of 1073741824 bytes) |
-mtime [+|-]# 修改时间/天
-ctime [+|-]# 改变时间/天
-atime [+|-]# 访问时间/天
-mmin[+|-]# 修改时间/分钟
-cmin [+|-]# 改变时间/分钟
-amin [+|-]# 访问时间/分钟
+表示#天(或分钟)以前,-表示#天(或分钟)以内,以下为图示,注意,数轴的方向表示文件某时间戳距此刻的时长,即正方向是指向过去的:
-perm MODE:精确匹配
/MODE: 任何一类用户(u,g,o)的任何一位(r,w,x)权限匹配
9位权限位
常用于查找某类用户的特定权限是否存在
只判断一位权限时,+和-一样
-MODE: 每一类用户都必须同时拥有为其制定的权限标准
例:
-a 与(and)
-o 或(or)
-not 非(NOT)
或!
若给出了多个查找条件而没有指定逻辑链接方式,默认为与(-a)
-print 输出至标准输出,默认操作
-ls 类似ls -l 的形式显示
-delete 删除查找到的文件
-fls /path/to/somefile
查找到的文件的长格式信息保存至指定文件中
-exec COMMAND {} \;
find把查找到的所有文件一次性地传递给-exec执行
执行命令,有些命令不接受过多参数,此时命令执行可能会失败,此时使用以下方式:
find | xargs COMMAND
{}是文件名占位符,用于引用查找到的文件名自身
注意:\;前必须有空格,\;二者之间不能都空格
-ok COMMAND {} \; 交互式-exec
例:查找/tmp下改变时间为5分钟以内的文件,在原文件名之后加上.new
find /tmp -cmin -5 -exec mv {} {}.new \;
不能使用管道将find的结果传递给以文件或路径为参数的命令来执行,因为管道传递的是路径,如
find /tmp -perm -003 | chmod o-x
是不可以的,因为chmod需要以文件路径作为参数
find /etc -perm -003 | tr 'a-z' 'A-Z'
可以,tr本就是处理字符串的命令
可以使用命令替换,如
chmod o-x `find /etc -perm -003`
但是同-exec,都可能出现命令参数溢出,因为find将找到的内容一次性输出,解决方式为:
find | xargs COMMAND
查找文件时,可以将查找到的内容管道送给xargs,执行操作,如
find /etc -perm -003 | xargs chmod o-x
①查找属组有写权限的文件,将其文件名改为原名后加.new
find ./ -perm -020 -exec mv {} {}.new \;
②查找所有用户都有执行权限的脚本,将其他用户的执行权限去掉
find ./ -name "*.sh" -a -perm -111 -exec chmod o-x {} \;
③查找/tmp中没有属组或没有属主的文件并显示
find /tmp \( -nouser -o -nogroup \) -ls
④找出/tmp目录下,属主不是root,且文件名不是fstab的文件
find /tmp \( -not -user root -a -not -name 'fstab' \) -ls
find /tmp -not \( -user root -o -name 'fstab' \) -ls
⑤查找/etc目录下最周一周内其内容修改过,同时属主不为root,也不是hadoop的文件或目录
find /etc -mtime -7 -a -not -user root -a -not -user hadoop
find /etc -mtime -7 -a -not \( -user root -o -user hadoop \)
⑥查找/etc目录下所有用户都没有写权限的文件
find /etc -not -perm /222
⑦查找/etc目录下至少有一类用户没有执行权限的文件
find /etc -not -perm -111
⑧查找/etc/init.d/目录下,所有用户都有执行权限且其他用户有写权限的文件
find /etc/init.d/ -perm -113
find /etc/init.d/ -perm -111 -o perm +002
find /etc/init.d/ -perm -111 -o perm -002
Tips: 只判断一位权限时,+和-一样
alias lftps='lftp 172.168.0.1/pub'
/bin/bash$
过滤出以/bin/bash结尾的行,使用grep -v选项取反即可:
[root@localhost ~]# grep -v "/bin/bash$" /etc/passwd
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
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
nobody:x:99:99:Nobody:/:/sbin/nologin
avahi-autoipd:x:170:170:Avahi IPv4LL Stack:/var/lib/avahi-autoipd:/sbin/nologin
dbus:x:81:81:System message bus:/:/sbin/nologin
polkitd:x:999:998:User for polkitd:/:/sbin/nologin
abrt:x:173:173::/etc/abrt:/sbin/nologin
sssd:x:998:997:User for sssd:/:/sbin/nologin
colord:x:997:995:User for colord:/var/lib/colord:/sbin/nologin
ntp:x:38:38::/etc/ntp:/sbin/nologin
libstoragemgmt:x:996:994:daemon account for libstoragemgmt:/var/run/lsm:/sbin/nologin
rpc:x:32:32:Rpcbind Daemon:/var/lib/rpcbind:/sbin/nologin
rtkit:x:172:172:RealtimeKit:/proc:/sbin/nologin
usbmuxd:x:113:113:usbmuxd user:/:/sbin/nologin
rpcuser:x:29:29:RPC Service User:/var/lib/nfs:/sbin/nologin
nfsnobody:x:65534:65534:Anonymous NFS User:/var/lib/nfs:/sbin/nologin
mysql:x:27:27:MariaDB Server:/var/lib/mysql:/sbin/nologin
tss:x:59:59:Account used by the trousers package to sandbox the tcsd daemon:/dev/null:/sbin/nologin
chrony:x:995:993::/var/lib/chrony:/sbin/nologin
pulse:x:171:171:PulseAudio System Daemon:/var/run/pulse:/sbin/nologin
gdm:x:42:42::/var/lib/gdm:/sbin/nologin
postfix:x:89:89::/var/spool/postfix:/sbin/nologin
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
tcpdump:x:72:72::/:/sbin/nologin
apache:x:48:48:Apache:/usr/share/httpd:/sbin/nologin
systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin
named:x:25:25:Named:/var/named:/bin/false
gentoo:x:5002:5002:Gentoo Distribution:/home/gentoo:/bin/csh
grep ".*[0-9]\{2,3\}.*" /etc/passwd
grep -i "^s" /proc/meminfo # 使用-i选项忽略大小写
grep "^[Ss]" /proc/meminfo # 使用范围过滤
grep -E "^(S|s)" /proc/meminfo # 使用扩展正则表达式
echo /etc/rc.d/init.d/network | egrep -o ".*/"
[root@localhost ~]# echo /etc/rc.d/init.d/network | egrep -o ".*/"
/etc/rc.d/init.d/
[root@localhost ~]# echo /etc/rc.d/init.d | egrep -o ".*/"
/etc/rc.d/
[root@localhost ~]# echo /etc/rc.d/init.d/ | egrep -o ".*/"
/etc/rc.d/init.d/
echo /etc/rc.d/init.d/network | sed 's@[^/]\{1,\}/\?$@@'
此处使用了sed的查找替换命令
s,其余vim的
s相似,关于sed,后续将做详细介绍
[root@localhost ~]# ifconfig
eno16777736: flags=4163 mtu 1500
inet 192.168.18.128 netmask 255.255.255.0 broadcast 192.168.18.255
inet6 fe80::20c:29ff:fecf:6af3 prefixlen 64 scopeid 0x20
ether 00:0c:29:cf:6a:f3 txqueuelen 1000 (Ethernet)
RX packets 24788 bytes 28299954 (26.9 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 10944 bytes 1072371 (1.0 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73 mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10
loop txqueuelen 0 (Local Loopback)
RX packets 24 bytes 2304 (2.2 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 24 bytes 2304 (2.2 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
ipv4使用点分十进制表示,此处使用的方法为:
ifconfig | egrep -o '\<([1-9]|[1-9][0-9]|1[0-9]{2}|2[01][0-9]|22[0-3])\>(\.\<([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-4])\>){2}\.\<([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-4])\>'
192.168.18.128
127.0.0.1
set autoindent
set tabstop=4
set shiftwidth=4
#!/bin/bash
# 5: user exits
declare -i sum_uid=0
addusers() {
if id $1 &> /dev/null; then
return 5
else
useradd $1
retval=$?
return $retval
fi
}
for i in {1..3}; do
addusers ${1}${i};
retval=$?
if [ $retval -eq 0 ]; then
echo "Add user ${1}${i} finished."
let sum_uid+=`id -u ${1}${i}`
elif [ $retval -eq 5 ]; then
echo "User ${1}${i} exists."
else
echo "Unknow error."
fi
done
echo "The sum of User ID is: $sum_uid."
执行结果:
[root@localhost scripts]# bash useradd-homework.sh user
Add user user1 finished.
Add user user2 finished.
Add user user3 finished.
The sum of User ID is: 15012.
后续将会介绍sed ↩︎