文件文本过滤与vim

文本主要介绍正则表达式、grep家族命令,以及vim与文件查找工具,如find与locate。

文章目录

  • 一、正则表达式
    • 0. 概念
    • 1. grep、egrep、fgrep
    • 2. 基本正则表达式(BRE)
      • Globbing回顾
      • BRE元字符
        • 字符匹配
        • 匹配次数
          • 贪婪模式
        • 位置锚定
        • 分组与引用
    • 3. 扩展正则表达式(ERE)
      • 字符匹配
      • 匹配次数
      • 位置锚定
      • 分组与引用
      • 或者
  • 二、vim
    • 1. 介绍
    • 2. 常用参数
    • 3. 模式间转换
    • 4. 常用通配符
    • 5. 编辑模式
      • 移动光标
        • 逐字符移动
        • 以单词为单位移动
        • 行内跳转
        • 行间跳转
        • 句子间跳转
        • 段落间跳转
      • 翻屏
      • 删除单个字符
      • 删除命令:d
      • 修改命令:c
      • 复制命令:y
      • 粘贴命令:p
      • 替换命令:r
      • 撤销
      • 重复之前的操作
      • 分屏显示
      • 关闭文件
    • 6. 可视化模式
    • 7. 末行模式
      • 打开文件
      • 关闭文件
      • 移动光标
      • 地址定界
      • 编辑操作
      • 查找
      • 查找并替换:s
      • 分屏显示
      • 文件间切换
      • 与shell交互
    • 8. 定制vim的工作特性
      • 显示或取消显示行号
      • 设定忽略或区分字符大小写
      • 设定自动缩进
      • 高亮搜索
      • 语法高亮
      • 高亮显示与之匹配的括号
    • 9. vim的配置文件
    • 10. 获取帮助
  • 三、文件查找
    • locate
    • find
      • 查找条件
        • 按文件名
        • 按文件归属
        • 按文件类型
        • 按文件大小
        • 按文件时戳
          • 以天为单位(time)
          • 以分钟为单位(min)
        • 按文件权限
      • 条件组合
      • 处理操作
      • 使用示例
  • 四、例

一、正则表达式

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匹配整行
^$ 空白行
^[[: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是一个模式化的编辑器,这里介绍常用几种模式

  • 编辑模式:默认处于该模式下,在该模式中,键盘操作通常被解释为编辑命令而非输入字符
  • 输入模式:该模式下键盘的输入将被录入到屏幕
  • 末行模式:即命令行模式,可在此进行复杂的操作
  • 可视化模式:便于快捷查看、选定等

其界面如下:
文件文本过滤与vim_第1张图片

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 [+|-]#			访问时间/分钟

+表示#天(或分钟)以前,-表示#天(或分钟)以内,以下为图示,注意,数轴的方向表示文件某时间戳距此刻的时长,即正方向是指向过去的:
文件文本过滤与vim_第2张图片

按文件权限

-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可进行较好过滤:
echo /etc/rc.d/init.d/network | sed 's@[^/]\{1,\}/\?$@@'
此处使用了sed的查找替换命令 s,其余vim的 s相似,关于sed,后续将做详细介绍
6、找出ifconfig中的ip地址。要求结果只显示IP地址
以下为ifconfig的输出结果:
[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
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用法以及常用用法的实例演示
见上文

  1. 后续将会介绍sed ↩︎

你可能感兴趣的:(Linux)