文本主要介绍正则表达式、grep家族命令,以及vim与文件查找工具,如find与locate。
一、正则表达式
0. 概念
正则表达式(REGular EXPression,REGEXP)使用单个字符串来描述、匹配一系列匹配某个句法规则的字符串的机制。它将一些字符作为元字符(Meta Characteristic) 用于标识一类字符或用于特殊限定,而不是标识其原有的字面意义。
在进行文本匹配时,我们所写的匹配表达式被称为模式(Pattern) ,而在Linux中,最常用的支持正则表达式的程序为grep家族程序,根据其划分,又分为:
- BRE(Basic RegEx),基本正则表达式
- ERE(Extended RegEx),扩展正则表达式
在介绍正则表达式之前,前介绍grep的用法
1. grep、egrep、fgrep
这三个命令类似,都用作文本过滤,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
模式,即用于匹配的条件,将在下面介绍
2. 基本正则表达式(BRE)
Globbing回顾
通配符 | 意义 |
---|---|
* | 任意长度的任意字符 |
? | 任意单个字符 |
[] | 指定范围内的任意单个字符 |
[^] | 指定范围外的任意单个字符 |
BRE元字符
正则表达式的介绍主要内容为介绍其元字符,分为以下几类:
- 字符匹配
- 次数匹配
- 位置锚定
- 分组
字符匹配
元字符 | 意义 |
---|---|
. | 匹配任意字符 |
[] | 匹配指定范围内的字符 |
[^] | 匹配指定范围外的字符 |
注意,这里只是确定匹配什么字符,匹配次数并不由此限制。
关于范围,可使用如下方式表示:
范围 | 意义 |
---|---|
[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$ | 用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.
例
- 显示/proc/meminfo文件中以不区分大小的s开头的行;
grep -i '^s' /proc/meminfo grep '^[sS]' /proc/meminfo
- 显示/etc/passwd中以nologin结尾的行;
grep 'nologin$' /etc/passwd
- 取出默认shell为/sbin/nologin的用户列表
grep "nologin$' /etc/passwd | cut -d: -f1
- 取出默认shell为bash,且其用户ID号最小的用户的用户名
grep 'bash$' /etc/passwd | sort -n -t: -k3 | head -1 | cut -d: -f1
- 显示/etc/inittab中以#开头,且后面跟一个或多个空白字符,而后又跟了任意非空白字符的行;
grep "^#[[:space:]]\{1,\}[^[:space:]]" /etc/inittab
- 显示/etc/inittab中包含了:一个数字:(即两个冒号中间一个数字)的行;
grep ':[0-9]:' /etc/inittab
- 显示/boot/grub/grub.conf文件中以一个或多个空白字符开头的行;
grep '^[[:space:]]\{1,\}' /boot/grub/grub.conf
- 显示/etc/inittab文件中以一个数字开头并以一个与开头数字相同的数字结尾的行;
grep '^\([0-9]\).*\1$' /etc/inittab
- 找出"netstat -tan"命令的结果中以’LISTEN’后跟0、1或多个空白字符结尾的行;
netstat -tan | grep "LISTEN[[:space:]]*$"
3. 扩展正则表达式(ERE)
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
二、vim
1. 介绍
同nano一样,vim也是一款全屏幕的编辑器,他是vi(visual Interface)编辑器的进化版(improved),功能异常强大。
vim是一个模式化的编辑器,这里介绍常用几种模式
- 编辑模式:默认处于该模式下,在该模式中,键盘操作通常被解释为编辑命令而非输入字符
- 输入模式:该模式下键盘的输入将被录入到屏幕
- 末行模式:即命令行模式,可在此进行复杂的操作
- 可视化模式:便于快捷查看、选定等
其界面如下:
2. 常用参数
vim [OPTIONS] /PATH/TO/SOMEFILE...
OPTIONS
-o 水平分割显示
-O 垂直分割显示
Ctrl+w,箭头 窗口间跳转
若打开单个文件,这里将不会分隔窗口
+N 打开文件并定位在第N行的行首
+/PATTERN 打开文件后,直接让光标处于第一个被PATTERN匹配到的行的行首
+ 打开文件并定位在最后一行
3. 模式间转换
-
编辑模式–>输入模式
- i:insert,在当前光标所在字符的前面,转换为输入模式
- a:append,在当前光标所在字符的后面,转换为输入模式
- o:在当前光标所在行的下方,新建一行,并转为输入模式
- I:在当前光标所在行的行首,转换为输入模式
- A:在当前光标所在行的行尾,转换为输入模式
- O:在当前光标所在行的上方,新建一行,并转换为输入模式 输入模式–>编辑模式
- ESC键 编辑模式–>末行模式
- : 末行模式–>编辑模式
- ESC
- 命令行有内容时可敲击多次ESC 编辑模式–>可视化模式
- v
4. 常用通配符
通配符 | 意义 |
---|---|
. | 当前行 |
$ | 最后一行 |
$-1 | 倒数第二行 |
+# | 向下的#行 |
5. 编辑模式
移动光标
逐字符移动
按键 | 动作 |
---|---|
h或← | 向左 |
l或→ | 向右 |
j或↓ | 向下 |
k或↑ | 向上 |
-
#COMMAND:可以移动#个字符如:
- 4l:向右移动4字符
- 6←:向左移动6字符
以单词为单位移动
按键 | 动作 |
---|---|
w | 移至下一个单词的词首 |
b | 调至当前或前一个单词词首 |
e | 跳至当前或下一个单词词尾 |
#COMMAND:可以移动#个单词
行内跳转
按键 | 动作 |
---|---|
0 | 数字0,跳至绝对行首 |
^ | 跳至行首的第一个非空白字符 |
$ | 跳至绝对行尾 |
行间跳转
按键 | 动作 |
---|---|
#G | 跳转至第#行 |
G | 跳转至最后一行 |
1G或gg | 跳转至第一行 |
句子间跳转
按键 | 动作 |
---|---|
) | 下一句 |
( | 上一句 |
段落间跳转
按键 | 动作 |
---|---|
} | 下一段 |
{ | 上一段 |
翻屏
按键 | 动作 |
---|---|
Ctrl+f | 向文件尾部翻一屏 |
Ctrl+b | 向文件首部翻一屏 |
Ctrl+d | 向文件尾部翻半屏 |
Ctrl+u | 向文件首部翻半屏 |
Enter | 按行向后翻 |
删除单个字符
按键 | 动作 |
---|---|
x | 删除光标所在处的单个字符 |
#x | 删除光标所在处及向后的共#个字符 |
删除命令:d
d命令跟跳转命令组合使用,用于删除光标当前位置到跳转到位置的字符,#d跳转符:如:
按键 | 动作 |
---|---|
3dw | 删除光标向后的3个单词 |
d^ | 删除至行首 |
d$ | 删除至行尾 |
dd | 删除当前光标所在行 |
#dd | 删除包括当前光标所在行在内的下#行 |
修改命令:c
即先删除内容,再转换为输入模式,用法同d命令,如
按键 | 动作 |
---|---|
c$ | 删除光标值行尾内容并转为输入模式 |
c^ | 删除光标值行首内容并转为输入模式 |
cc | 删除光标所在行内容并转为输入模式 |
#cc | 删除包括当前光标所在行在内的下#行并转为输入模式 |
复制命令:y
使用方法同删除命令,如
按键 | 动作 |
---|---|
c$ | 复制光标值行尾内容 |
c^ | 复制光标值行首内容 |
cc | 复制光标所在行内容 |
#cc | 复制包括当前光标所在行在内的下#行 |
粘贴命令:p
vim中编辑的内容可以撤销,最后一次删除的内容会被保存至内存的缓冲区中,可以用于下次粘贴至他处,相当于剪切
-
p(小写)
- 如果删除或复制的内容为整行内容,则粘贴至光标所在行的下方;
- 如果删除或复制的内容为非整行,则粘贴至光标所在字符的后面; P(大写)
- 如果删除或复制的内容为整行内容,则粘贴至光标所在行的上方;
- 如果删除或复制的内容为非整行,则粘贴至光标所在字符的前面
替换命令:r
先按r,再按下字符,可以将当前光标所在的字符替换的键入的字符
#r:向后替换#个字符
可敲R进入替换模式,替换模式下键入的字符将直接替换原字符
撤销
按键 | 动作 |
---|---|
u | 撤销前一次的编辑操作 |
#u | 撤消指定次数的操作 |
U | 仅撤销光标所在行的编辑操作 |
Ctrl+r | 还原撤销 |
连续u命令可撤消此前的n次编辑操作,默认最多撤销50次操作
重复之前的操作
在编辑模式中,使用.可重复之前的操作
分屏显示
按键 | 动作 |
---|---|
Ctrl+w, s | 水平拆分窗口 |
Ctrl+w, v | 垂直拆分窗口 |
在窗口键切换的方式为:Ctrl+w,箭头
关闭文件
ZZ (大写)保存并退出
6. 可视化模式
该模式可以选中光标划过的所有字符
按键 | 动作 |
---|---|
v | 按字符选取 |
V | 按行选取 |
经常结合编辑命令:d,c,y
7. 末行模式
打开文件
按键 | 动作 |
---|---|
: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
在末行模式下使用s命令,用法同sed中的s命令1
s命令默认只替换每行中第一次被模式匹配到的字符串,其使用格式为:
:地址定界s/查找模式/替换为的内容/修饰符
-
分隔符
- /为分隔符,可以换成其他字符,如s### s@@@ …
- 紧跟在s之后的字符,会被解析成定界符
- 若pattern中或string中有与分隔符相同的,使用\转义 查找模式
- 这里的模式支持正则表达式 替换为的内容
- 替换为的内容不支持正则表达式,但可以使用\1, \2, … 等后向引用,还可以使用&引用前面查找时查找到的整个内容 修饰符
-
修饰符 意义 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 | 切换至第一个文件 |
与shell交互
即在vim中执行shell命令,在末行模式下输入!,后跟命令即可。
若在vim中编辑了内容,在未保存的情况下意外关闭,在下次编辑时vim将会警告,可以使用vim -r 恢复未保存的数据,删除同目录下的*.swp文件,亦可在警告窗口中根据提示进行操作
8. 定制vim的工作特性
在末行模式下使用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进程
9. vim的配置文件
vim有两种配置文件
- /etc/vimrc:对所有用户生效
- ~/.vimrc:仅对当前用户生效,若不存在,可自行创建
通过将以上属性设置指令写入配置文件,可永久生效
10. 获取帮助
vim是一个很复杂的工具,这里介绍的只是基础用法,关于帮助的获取,可使用如下方式:
- : help:在末行模式下输入help和查看vim的帮助
- : help SUBJECT:help后跟一个关键字可查看该部分帮助
另外,vimtutor
命令中有关于vim的相关教程
三、文件查找
前文介绍的grep家族工具用作文本过滤,他们作用于文件时,是过滤文件内容,而此处介绍的文件查找工具,将通过特定条件,查找文件本身。
locate
该命令将通过文件名查找文件,基本使用格式为:
locate [OPTION]... PATTERN…
[OPTION]
-b:只匹配基名
-c:统计出共有多少个符合条件的文件
-r:基于BRE(基本正则表达式)搜索
需要说明的是,find的查找是根据全系统数据库进行的,系统将在任务计划的配置下,在设定时间将系统上的文件信息收集到全系统数据库中,locate将在这个数据库中进行查找,速度较快,但由于是基于该索引,故其结果并非实时。
如当前新建了一个文件,呃索引数据尚未建立该条目,则locate将无法找到该文件,欲手动生成文件数据库,可使用updatedb
命令构建索引
注意,索引构建过程需要遍历整个根文件系统,极其消耗资源
find
与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) |
-
指定大小查找时,若没有指定+或-,会匹配在给定大小为1单位一内的所有文件即
- #表示(#-1, #]
- -#表示[0, #-1]
- +#表示(#, ∞)
按文件时戳
以天为单位(time)
-mtime [+|-]# 修改时间/天
-ctime [+|-]# 改变时间/天
-atime [+|-]# 访问时间/天
以分钟为单位(min)
-mmin[+|-]# 修改时间/分钟
-cmin [+|-]# 改变时间/分钟
-amin [+|-]# 访问时间/分钟
+表示#天(或分钟)以前,-表示#天(或分钟)以内,以下为图示,注意,数轴的方向表示文件某时间戳距此刻的时长,即正方向是指向过去的:
按文件权限
-perm MODE:精确匹配
/MODE: 任何一类用户(u,g,o)的任何一位(r,w,x)权限匹配
9位权限位
常用于查找某类用户的特定权限是否存在
只判断一位权限时,+和-一样
-MODE: 每一类用户都必须同时拥有为其制定的权限标准
例:
-
文件权限644
- -perm 644 查找文件权限为644的文件,可以匹配
- -perm /222 查找有用户有写权限的文件,可以匹配
- -perm /002 查找其他用户有写权限的文件,不能匹配
- -perm -444 可以匹配
条件组合
-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
-
xargs
- build and execute command lines from standard input
- xargs命令是给其他命令传递参数的一个过滤器,也是组合多个命令的一个工具。它擅长将标准输入数据转换成命令行参数,xargs能够处理管道或者stdin并将其转换成特定命令的命令参数。xargs也可以将单行或多行文本输入转换为其他格式,例如多行变单行,单行变多行。xargs的默认命令是echo,空格是默认定界符。这意味着通过管道传递给xargs的输入将会包含换行和空白,不过通过xargs的处理,换行和空白将被空格取代。xargs是构建单行命令的重要组件之一
使用示例
①查找属组有写权限的文件,将其文件名改为原名后加.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: 只判断一位权限时,+和-一样
四、例
-
1、定义一个对所有用户都生效的命令别名,例如:lftps=‘lftp 172.168.0.1/pub’
- 相关的说明见另一篇文章: https://blog.csdn.net/xiyangyang410/article/details/85454040#bash_51
- 此处可编辑/etc/bashrc文件,在代码块最外层写入:
-
alias lftps='lftp 172.168.0.1/pub'
2、显示/etc/passwd文件中不以/bin/bash结尾的行
-
使用模式
/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
3、找出/etc/passwd文件中,包含二位数字或者三位数的行
-
grep ".*[0-9]\{2,3\}.*" /etc/passwd
4、显示/proc/meminfo文件中以大写或小写S开头的行;用三种方式实现
-
grep -i "^s" /proc/meminfo # 使用-i选项忽略大小写 grep "^[Ss]" /proc/meminfo # 使用范围过滤 grep -E "^(S|s)" /proc/meminfo # 使用扩展正则表达式
5、使用echo输出一个绝对路径,使用egrep取出路径名,类似执行dirname /etc/passwd 的结果
-
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/
-
暂未想到使用egrep的一个比较好的解决方法,使用sed可进行较好过滤:
此处使用了sed的查找替换命令 s,其余vim的 s相似,关于sed,后续将做详细介绍echo /etc/rc.d/init.d/network | sed 's@[^/]\{1,\}/\?$@@'
6、找出ifconfig中的ip地址。要求结果只显示IP地址
-
以下为ifconfig的输出结果:
ipv4使用点分十进制表示,此处使用的方法为:[root@localhost ~]# ifconfig eno16777736: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> 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<link> 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<UP,LOOPBACK,RUNNING> mtu 65536 inet 127.0.0.1 netmask 255.0.0.0 inet6 ::1 prefixlen 128 scopeid 0x10<host> 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
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
7、vim定制自动缩进四个字符
-
配置自动缩进为set autoindent,同时修改tab缩进的长度,以及将其自动转为空格,将以下内容写入配置文件中即可:
set autoindent set tabstop=4 set shiftwidth=4
- 如上文介绍,将其写入/etc/vimrc对所有用户生效,写入~/.vimrc仅对当前用户生效 8、编写脚本,实现自动添加三个用户,并计算这三个用户的uid之和
- 关于脚本编写运行的基础介绍,可参考 https://blog.csdn.net/xiyangyang410/article/details/85454040#4__323
-
此处的实现为:
执行结果:#!/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.
9、find用法以及常用用法的实例演示
- 见上文
后续将会介绍sed ↩︎