1文本处理
1.1文本处理
1.1.1vi&vim
在Linux中我们经常编辑修改文本文件,即由ASCII, Unicode 或其它编码的纯文字的文件。实际工作
中我们会使用更为专业,功能强大的文本编辑工具。这些常见的文本编辑工具主要有两大类:
- 全屏编辑器:nano(字符工具), gedit(图形化工具),vi,vim
- 行编辑器:sed
vi&vim
VI:
Visual editor,文本编辑器,是 Linux 必备工具之一,功能强大,学习曲线较陡峭,学习难度大。
vi是Unix系统自带的编辑器,在几乎所有的Unix或类Unix系统上都可以使用。
VIM:
VIsual editor iMproved ,vim是vi的改进版本,全称是Vi IMproved。
它在保留vi所有功能的基础上,添加了许多新特性,支持语法高亮等功能,使得代码编辑更加直观。和 vi 使用方法一致,vim的命令和快捷键也更加丰富和复杂,需要一定的学习成本。
VIM官网:https://www.vim.org
1.1.2vim模式
-
正常模式(Normal Mode)- 默认模式
操作示例: 光标移动:使用h、j、k、l键分别向左、下、上、右移动光标(或使用方向键)。 删除字符:按x删除光标所在位置的字符,按dd删除整行。 复制粘贴:使用yy复制当前行,p粘贴到光标所在位置。
-
编辑模式(Insert Mode)
进入方式: 从命令模式通过如下按键进入插入模式 - 按 i 在当前光标位置插入 - 按 a 在当前光标位置的下一个字符处插入 - 按 o 在当前光标所在行的下一行插入新行 - 按 O 在当前光标所在行的上一行插入新行 退出方式: 按Esc键退出插入模式,返回到命令模式。
-
命令模式(Last Line Mode 或 Command-line Mode)
操作示例: 保存文件:输入:w保存当前文件,:wq或:x保存并退出Vim 查找替换:输入:/搜索词进行查找,:s/原词/新词/g进行全局替换。 设置选项:输入:set nu显示行号,:set nonu取消显示行号。
-
使用vim打开一个文件 ,直接进入正常模式
-
注意: - 如果该文件存在,文件被打开并显示内容 - 如果该文件不存在,当编辑后第一次存盘时创建它 - 如果后面打开的是一个目录,则会列出目录中所有内容,可以用方向键进行选择 - 如果文件所在目录不存在,可以进行文件的编辑,但是无法保存
-
1.1.3编辑查找
-
打开文件直接到n行
- 默认打开一个新的文件光标处于首行的行首
+ #打开文件让光标处于末尾行 +n #打开光标,让光标处于第n行的行首 +/匹配项 #让光标处于第一个被匹配项匹配到的行行首 -d 文件名1 文件名2 #同时打开多个文件,相当于vimdiff
-
打开多个文件时使用快捷键切换两边的窗口
使用快捷键 Ctrl-w + w: Ctrl-w 是窗口切换的前缀键。 按下 Ctrl-w 后,再按下 w 会在当前可见的所有窗口之间循环切换。 或者 Ctrl-w + h【左】 | l【右】 | j【下】 | k【上】
-
一次性退出多个文件
进入命令模式,输入 qall #不保存退出全部 wqall #保存退出全部
-
从正常模式进入编辑模式的方法
-
i #insert, 在光标所在处输入 I #在当前光标所在行的行首输入 a #append, 在光标所在处后面输入 A #在当前光标所在行的行尾输入 o #在当前光标所在行的下方打开一个新行 O #在当前光标所在行的上方打开一个新行
-
-
查找
-
按 Esc 从编辑模式退出进入正常模式,而后按 : 进入命令模式
/关键字 #从当前光标所在处向文件尾部查找 ?关键字 #从当前光标所在处向文件首部查找 n #向下选择 N #向上选择
-
-
扩展
常用的: :wq 或 ZZ #写入并退出 :q!或 ZQ #不存盘退出,即使更改都将丢失 其他的: w #写(存)磁盘文件 x #写入并退出 X #加密(在命令模式输入“:set key=”命令,清楚加密密码,然后用wq保存退出。:::) q #退出 q! #不存盘退出,即使更改都将丢失 r 文件名 #读文件内容到当前文件中 w 文件名 #将当前文件内容写入另一个文件 !命令 #执行命令(在命令模式下直接执行外部命令,并显示输出结果) r!命令 #读入命令的输出(可以执行外部命令并将其输出内容插入到当前光标位置)
1.1.4扩展命令
常用的:
:wq 或 ZZ #写入并退出
:q!或 ZQ #不存盘退出,即使更改都将丢失
其他的:
w #写(存)磁盘文件
x #写入并退出
X #加密
q #退出
q! #不存盘退出,即使更改都将丢失
r filename #读文件内容到当前文件中
w filename #将当前文件内容写入另一个文件
!command #执行命令
r!command #读入命令的输出
1.1.5边界范围
-
筛选范围(都是在命令模式下)
使用方式: :起始位置,结束位置 命令 常用属性 M,N #从左侧M表示起始行,到右侧N表示结尾行 $ #最后一行 % #全文, 相当于1,$ /pat1/,/pat2/ #从第一次被pat1模式匹配到的行开始,一直到第一次被pat2匹配到的行结束 其他属性 N #具体第N行,例如2表示第2行 M,+N #从左侧M表示起始行,右侧表示从光标所在行开始,再往后+N行结束 M,-N #从左侧M表示起始行,右侧表示从光标所在行开始,-N所在的行结束 M;+N #从第M行处开始,往后数N行,2;+3 表示第2行到第5行,总共取4行 M;-N #从第M-N行开始,到第M行结束 . #当前行 .,$-1 #当前行到倒数第二行 /pattern/ #从当前行向下查找,直到匹配pattern的第一行,即正则匹配 /pat1/,/pat2/ #从第一次被pat1模式匹配到的行开始,一直到第一次被pat2匹配到的行结束 N,/pat/ #从指定行开始,一直找到第一个匹配pattern的行结束 /pat/,$ #向下找到第一个匹配patttern的行到整个文件的结尾的所有行
-
筛选后动作(正常模式下)
常用动作 d #删除 p #粘贴 y #复制 u #撤销刚才的动作 其他动作 w #file 将范围内的行另存至指定文件中 r file #在指定位置插入指定文件中的所有内容 t行号 #将前面指定的行复制到N行后 m行号 #将前面指定的行移动到N行后
vim a.txt "shsdgsahfgashfhafahsgfkjasckbadfb" #在正常模式下输入“ di" ”,删除""里面的所有内容。()也同理
动作演示
- 正常模式下
5dd #删除5行 5yy #复制5行 p #粘贴 dd #删除光标当前行 yy #复制 di" #删除当前光标所在行的引号("")里面的所有内容
- 命令模式下
:2d #删除第2行 :2,4d #删除第2到第4行 :2;+3y #复制第2到第5行,总共4行 :2;+4w test #将第2到第6行,总共5行内容写入新文件 :5r /etc/issue #将/etc/issue 文件读取到第5行的下一行 :t2 #将光标所在行复制到第2行的下一行 :2;+3t10 #将第2到第5行,总共4行内容复制到第10行之后 :.d #删除光标所在行 :$y #复制最后一行
1.1.6内容替换
-
方法
:s/要查找的内容/替换为的内容/修饰符 :%s 表示全文查找替换 注意: 修饰符不写默认替换第一个。 要查找的内容:可使用基本正则表达式模式 替换为的内容: 不能使用模式,但可以使用\1, \2, ...等后向引用符号; 还可以使用“&”引用前面查找时查找到的整个内容
-
修饰符
i 忽略大小写 g 全局替换,默认情况下,每一行只替换第一次出现 gc 全局替换,每次替换前询问
-
4,15 #第四行到第15行 /key1/,/key2/ #从key1的位置到key5的位置 , #表示当前行 $ #表示末尾行 % #表示全文
-
实例
从全文替换 :%s/原内容/替换后内容/g 从当前行到最后一行进行替换 :,$s/原内容/替换后内容/g 正则匹配内容进行全文替换 :/关键字/,$s/原内容/替换后内容/g 从第3到第6行内容进行替换 :3,6s/原内容/替换后内容/g
当前行替换——如果没有匹配的则不替换 :s/root/ROOT/ #替换当前行第一个root :s/root/ROOT/g #替换当前行所有root 全文替换 :%s/root/ROOT/g #全文替换 :%s/root/test/ig #不区分大小写全文替换 :%s/#// #将每行第一个#替换成空 范围替换 :/lp/,$s/sbin/SBIN/g # 从lp 关键字所在行,到文件末尾 :,$s/sbin/SBIN/g # 从当前行到文件末尾进行替换 :3,6s/sbin/SBIN/g # 3-6 行进行内容替换
-
1.1.7属性定制
- 常用属性
查看行号
:set number|set nu #显示行号
:set nonumber|set nonu #取消显示行号
复制保留格式
:set paste #复制时保留格式
:set nopaste #禁用复制时保留格式选项
Tab 用空格代替
:set expandtab|set et #使用空格代替Tab,默认8个空格
:set noexpandtab|set noet #禁用空格代替Tab
Tab用指定空格的个数代替
:set tabstop=N|set ts=N #指定N个空格代替Tab
查看帮助
:help option-list
:set|:set all
- 一般属性
忽略字符的大小写
:set ignorecase|set ic #忽略字符大小写
:set noignorecase|set noic #不忽略
自动缩进
:set autoindent|set ai #启用自动缩进
:set noautoindent|set noai #禁用自动缩进
显示Tab ^I和换行符 和$显示
:set list #显示系统字符
:set nolist #隐藏系统字符
高亮搜索
:set hlsearch #高亮显示搜索结果
:set nohlsearch|nohl #不高亮显示搜索结果
注意:是否显示高亮,需要系统来判断是否是关键的文件,如果关键则显示高亮,否则不管你
设置缩进宽度
按2个> #向右缩进 命令模式
按2个< #向左缩进 命令模式
:set shiftwidth=4 #设置缩进为4个字符
文件格式
:set fileformat=dos|set ff=dos #启用windows格式
:set fileformat=unix|set ff=unix #启用unix格式:
设置光标所在行的标识线
:set cursorline|set cul #给光标所在行加下划线
:set nocursorline|set nocul #取消光标下划线
加密
:set key=password #加密文档
:set key= #取消加密
1.1.8光标跳转
-
属性:
-
行首行尾跳转
^ #跳转至行首的第一个非空白字符 0 #跳转至行首 $ #跳转至行尾
-
行走间移动
NG|:N #跳转至指定行,N表示正整数,比如 10G,或在扩展命令模式下:10,都表示跳转到第10行 G #最后一行 gg|1G #第一行
-
字符间跳转
h #左 L #右,小写字母 j #下 k #上 Nh|Nl|Nj|Nk #每次跳转N个长度 2h表示向左移两个字符,3j表示向下走3行
-
单词间跳转
w #下一个单词的词首 e #当前或下一单词的词尾 b #当前或前一个单词的词首 Nw|Ne|Nb #一次跳N个单词
-
当前页跳转
H #页首 M #页中间行 L #页底 zt #将光标所在当前行移到屏幕顶端 zz #将光标所在当前行移到屏幕中间 zb #将光标所在当前行移到屏幕底端
-
句间移动:
) #下一句 ( #上一句
-
段落间移动:
} #下一段 { #上一段
-
命令模式翻屏操作
Ctrl+f #向文件尾部翻一屏,相当于Pagedown Ctrl+b #向文件首部翻一屏,相当于Pageup Ctrl+d #向文件尾部翻半屏 Ctrl+u #向文件首部翻半屏
-
1.1.9编辑进阶
-
常用编辑
-
粘贴:
p #小写,如果为整行,则粘贴当前光标所在行的下方;否则,则粘贴至当前光标所在处的后面 P #大写,如果为整行,则粘贴当前光标所在行的上方;否则,则粘贴至当前光标所在处的前面
-
复制:
yy|Y #复制整行,yy前面加数字,表示从当前处往后复制多少行; 3yy 表示往下复制3行 NYY #从当前处往后复制N行, N表示正整数,2yy表示从当前行开始,总共复制2行
-
删除
d #删除命令,可结合光标跳转字符,实现范围删除 d^ #删除光标处到非空行首 d0 #删除光标处到处行首 dw #从光标处删到下一个单词的词首 de #从光标处删到当前单词词尾或下一单词的词尾 db #从光标处删到当前单词词首或前一单词的词首 #这些内容都在缓冲区,可以用p键粘贴出来
-
撤销更改
u #撤销最近的更改,相当于windows中ctrl+z U #撤消光标落在这行后所有此行的更改 Ctrl+r #重做最后的“撤消”更改,相当于windows中crtl+y
-
-
其他编辑
-
字符编辑
x #剪切光标处的字符 Nx #剪切光标处起始的N个字符,N为正整数 xp #交换光标所在处的字符及其后面字符的位置,本质是先剪切,再粘贴 ~ #转换大小写 J #删除当前行后的换行符,就是把下一行接到当前行后面
-
替换命令
r #只替换光标所在处的一个字符,先敲r,再输入想要替换的新字符 R #切换成REPLACE模式(在末行出现-- REPLACE -- 提示),按ESC回到命令模式
-
删除命令(delete)
d #删除命令,可结合光标跳转字符,实现范围删除 d^ #删除光标处到非空行首 d0 #删除光标处到处行首 dw #从光标处删到下一个单词的词首 de #从光标处删到当前单词词尾或下一单词的词尾 db #从光标处删到当前单词词首或前一单词的词首 #这些内容都在缓冲区,可以用p键粘贴出来
-
复制命令(yank)
y #复制,行为相似于d命令 y$ #复制光标处到行尾 y0 #复制光标处到行首 y^ #复制光标处到非空行首 yw #从光标处复制到下一个单词的词首 ye #从光标处复制到当前单词词尾或下一单词的词尾 yb #从光标处复制到当前单词词首或下一单词的词首
-
改变
c$|C #删除光标处到行尾,并切换成插入模式 c^ #删除光标处到非空行首,并切换成插入模式 c0 #删除光标处到行首,并切换成插入模式 cc #删除当前行并输入新内容,相当于S,加数字表示向下删除多少行,然后切换成插入模式 Ncc #N表示正整数 cw #从光标处删到下一个单词的词首,并切换成插入模式 ce #从光标处删到当前单词词尾或下一单词的词尾,并切换成插入模式 cb #从光标处删到当前单词词首或下一单词的词首,并切换成插入模式
-
撤销更改
Nu #撤销之前多次更改,N表示正整数 . #重复前一个操作 N. #重复前一个操作N次,N为正整数
-
高阶管理
0y$ #复制整行,0表示到行首,y表示复制,$表示行尾,连起来就是复制整行 di" #光标在" "之间,则删除" "之间的内容 yi( #光标在()之间,则复制()之间的内容 vi[ #光标在[]之间,则选中[]之间的内容 dtx #删除字符直到遇见光标之后的第一个 x 字符 ytx #复制字符直到遇见光标之后的第一个 x 字符 10iabc ESC #在光标处插入10个abc
-
1.2vim高阶
1.2.1专属配置(.vimrc)
vimrc文件是vim编辑工具的一套预定义规则文件,在该文件中,我们可以通过设定一些常见的vim操作属性来帮助我们用vim工具编辑文件的时候,达到整体工作效率的提升。
注意:
在涉及到.vimrc相关属性配置操作的时候,需要大家对于vim的常见操作和属性操作有一定的经验。
-
vimrc文件信息
vimrc文件一般有两种形态:系统级别和用户级别。 - 系统级别的vimrc文件在 /etc/路径下,不是隐藏文件。 - 用户级别的.vimrc 文件位于 $HOME/ 目录下,是一个隐藏文件。 一般情况下,该文件是不存在的,需要手工创建。
set tabstop=4 " 设置制表符宽度为4 set shiftwidth=4 " 设置缩进宽度为4 set expandtab " 使用空格代替制表符进行缩进 set number " 显示行号 syntax on " 启用语法高亮 set background=dark " 设置背景色为深色 colorscheme desert " 设置颜色主题为desert
-
vimrc函数语法
自动执行命令格式: autocmd 事件 文件对象 执行命令 文件对象: BufNewFile 创建一个新文件 BufRead 读取一个文件 执行命令: exec 执行命令 :call 函数名 表示调用自定义函数。 call 函数名 表示调用vim程序函数 定义函数: function 函数名() 函数体 endfunction
-
定制一个通用的vimrc配置,让我们在编辑所有 .sh 后缀文件的时候,自动添加文件
set tabstop=2 set shiftwidth=2 set expandtab set number set autoindent set cursorline set showmatch syntax on set background=dark colorscheme desert
1.2.2可视化模式
-
在vim的正常模式下,按 Ctrl + v 就可以进入到可视化模式,在可视化模式下,我们就可以随意的批量对整个文件进行 编辑。
-
v的选择
v(小写) #面向字符 V(大写) #面向整行 ctrl-v(小写) #面向块
-
简单实践
-
在文件指定行的行首插入#
1、先将光标移动到指定的第一行的行首 2、输入ctrl+v 进入可视化模式 3、向下移动光标,选中希望操作的每一行的第一个字符 4、输入大写字母 I 切换至插入模式 5、输入 # 6、按 ESC 键
-
在指定的块位置插入相同的内容
1、光标定位到要操作的地方 2、CTRL+v 进入“可视块”模式,选取这一列操作多少行 3、SHIFT+i(I) 4、输入要插入的内容 5、按 ESC 键
-
1.2.3多文件模式
-
多文件之间切换
vim file1 file2 #多文件之间切换 :next #切换到下一个文件 :prev #切换到上一个文件
-
多文件切割
vim -o|-O file1 file2 ... -o #水平或上下分割 -O #垂直或左右分割(vim only) :wqall #退出 Ctrl+w, 方向键 #在窗口间切换
1 按 Esc 退出编辑模式 2 按 Ctrl + w 同时按 3 按 左右 | 上下箭头 4 按 i | a | o 等字符进入编辑模式
1.2.4单文件切割
-
属性:
Ctrl+w,s # split, 水平分割,上下分屏 Ctrl+w,v # vertical, 垂直分割,左右分屏 ctrl+w,q # 取消相邻窗口 ctrl+w,o # 取消全部窗口 :wqall # 退出 Ctrl+w, 方向键 # 在窗口间切换,Arrow 表示方向键
1.2.5帮助内容(help、vimtutor)
-
查看帮助
:help :help 命令 #比如 :help yy 就表示查看yy命令的用法 :q #退出help
-
列出主题
:help index #将带你到帮助系统的索引页面,使用搜索功能: 如果你在帮助文档中需要查找特定的主题,可 以使用 / 键进行搜索。例如,输入 /插入模式 来查找与插入模式相关的帮助内容。 #返回到之前的帮助: 在帮助文档中,可以使用 Ctrl + o 返回到之前的帮助页面。
-
帮助程序
vimtutor
vimtutor zh #以中文的方式显示帮助程序
总结
进入编辑模式 a i o O
保存文件 wq w q w! q!
文件编辑:
替换:
全文替换 %s/xxx/XXX/g
范围替换 4,9S/xxx/XXXg
删除:dd ndd dG dgg
粘贴:p
复制:yy nyy
定位:
/关键字/ 确定键
/ 向下找 ? 向上找
^ 行首 $ 行尾 gg 首行 G 尾行 :n 切换到n行
块编辑
Ctrl + v
光标移动
插入编辑:I+编辑+esc
批量删除:d
1.3内容查看
1.3.1文件查看(cat、nl、tac、rev、hexdump)
-
cat 查看文件内容
格式 cat 选项... 文件名 ... 选项 -n #对显示出的每一行进行编号 -s #压缩连续空行成一行
-
nl 查看文件的时候显示行号
格式 nl 文件名... 相当于cat -b
-
tac 逆向显示文件内容
格式 tac 文件名...
-
rev 内容逆向显示,但行内容也逆向显示
格式 rev 文件名...
-
hexdump 以十六进制方式查看任意文件
格式 dexdump 选项 文件名 选项 -C,-canonical #规范化hex+ASCII显示
1.3.2分页查看(more,less)
-
more ——可以实现分页查看文件,可以配合管道实现输出信息的分页
格式 more 选项... 文件名... 选项 -d #在底部显示提示 -s #压缩连续空行 动作 空格键 #翻页 回车键 #下一行 q #退出 其他动作 !命令 #执行命令,在查看文档的时候,执行相关的命令 h #显示帮助 :f #显示文件名和当前行号 = #显示行号
-
less ——也可以实现分页查看文件或STDIN输出,less 命令是man命令使用的分页器
命令格式 less [选项...] 文件名... 选项 -e #显示完成后自动退出 -N #显示行号 -s #压缩连续空行 -S #不换行显示较长的内容 动作 :h #显示帮助 /string #搜索 :!命令 #执行命令在查看文档的时候,执行相关的命令 b #向上翻
1.3.3头尾查看(head、tail)
-
head ——可以显示文件或标准输入的前面行
格式 head 选项... 文件名... 默认查看文件前10行 选项 -n #指定获取前n行,n如果为负数,表示从文件头取到倒数第N行前 -c|--bytes=n #指定获取前n字节
-
tail——查看文件或标准输入的倒数行
格式 tail 选项... 文件名... 默认查看文件后10行 选项 -n #指定获取后N行,如果写成+N,表示从第N行开始到文件结束 -c|--bytes=N #指定获取后N字节 -f|--follow=descriptor #跟踪显示文件fd新追加的内容,常用日志监控, #当删除再新建同名文件,将无法继续跟踪 -F|--follow=name --retry #跟踪文件名,相当于--follow=name --retry, #当删除文件再新建同名文件,可继续追踪
-
综合实践
head -n6 a.txt | tail -n1 #显示a.txt中第六行的内容
命令 含义 示例 head -n k file 取 file 前 k行内容 head -n 3 /etc/passwd head -k file 取 file 前 k行内容 head -3 /etc/passwd head -n +k file 取 file 前 k行内容 head -n +3 /etc/passwd head -n -k file 取file 第1行到倒数第k行内容 head -n -3 /etc/passwd tail -n k file 从后往前数,取file 第1行到第k行内容 tail -n 3 /etc/passwd tail -k file 从后往前数,取file 第1行到第k行内容 tail -3 /etc/passwd tail -n -k file 从后往前数,取file 第1行到第k行内容 tail -n -3 /etc/passwd tail -n +k file 从后往前数,取file 第1行到倒数第k行内容 tail -n +3 /etc/passwd
1.3.4切割替换(cut、tr)
-
cut ——命令可以提取文本文件或STDIN数据的指定列
格式 cut 选项... 文件... 选项 -c #只选中指定的这些字符 -d #使用指定分界符代替制表符作为区域分界 -b #只选中指定的这些字节
# cut -d: -f1 1.txt 以:冒号分割,截取第1列内容 # cut -d: -f1,6,7 1.txt 以:冒号分割,截取第1,6,7列内容 # cut -c4 1.txt 截取文件中每行第4个字符 # cut -c1-4 1.txt 截取文件中每行的1-4个字符 # cut -c5- 1.txt 从第5个字符开始截取后面所有字符
-
tr——命令实现 字符转换、替换、删除
格式 tr 选项... 文件名 选项 -c #取反 -d #删除 -s #压缩
root@rocky9:~ $ echo "Hello, World! 123" | tr -c 'A-Za-z' '\n' Hello World
root@rocky9:~ $ echo "Hello, World! 123" | tr -d 'A-Za-z' , ! 123
root@rocky9:~ $ echo "Hello, World! 123" | tr -s 'A-Za-z' Helo, World! 123
-
实践
head -n5 a.txt | cut -d: -f1,3,4,7 #取文件a.txt中前五行以":"为分隔符,的第1,3,4,7个字符 root@rocky9:~ $ ip a show ens160 | head -4 | tail -1 | tr '/' ' ' | cut -d" " -f 6 10.0.0.11 root@rocky9:~ $ ip a show ens160 | head -n4 | tail -1 | tr -s " " | cut -d " " -f 3 | cut -d "/" -f1 10.0.0.11 #查看ip地址 head -n5 /etc/passwd | cut -d: -f1,3,7 --output-delimiter="---" #将分隔符替换为“---”
root@rocky9:~ $ cat b.txt 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 root@rocky9:~ $ tr '[a-z]' '@' < b.txt @@@@:@:0:0:@@@@:/@@@@:/@@@/@@@@ @@@:@:1:1:@@@:/@@@:/@@@@/@@@@@@@ @@@@@@:@:2:2:@@@@@@:/@@@@:/@@@@/@@@@@@@ @@@:@:3:4:@@@:/@@@/@@@:/@@@@/@@@@@@@ @@:@:4:7:@@:/@@@/@@@@@/@@@:/@@@@/@@@@@@@
-
总结
关于cut -c -5 #0-5的所有内容 6- #6-末尾的所有内容 关于cut -d cut -d "分隔符" -f列 打印内容 tr "原内容" "替换后的内容"
1.3.5信息排序(sort、uniq)
-
sort命令,实现信息排序
格式 sort 格式 文件名 将文件的每一行作为一个单位,从首字符向后,依次按ASCII码值进行比较,最后将他们按升序输出。 选项 -u #去除重复行 -r #降序排列,默认是升序 -n #以数字排序,默认是按字符排序
-
uniq命令 实现连续信息的去重动作
格式 uniq 文件名 选项 -c, --count #统计重复行次数 -d, --repeated #只显示重复行 -i, --ignore-case #忽略大小写
sort -nu num.txt #升序去重 sort -ru num.txt #降序去重 sort -nru num.txt #先升序后降序再去重 sort -R num.txt #随机排序 sort -nu num.txt -o /tmp/a.txt #升序去重后输出到一个文件
1.3.6内容合并(paste、xargs)
-
paste——合并文件行内容输出到屏幕,不会改动源文件
格式 paste 选项... 文件名... 选项 -d DELIM #指定分隔符,默认为制表符(Tab)。 -s #将行合并为单行,输出为列而不是行。 -z #使用空字符作为行分隔符,而不是换行符
root@rocky9:~ $ paste 2.txt -s -d"@" nihao@999@888@777
-
xargs命令结果传递
- xargs 可以将管道或标准输入(stdin)数据转换成命令行参数,也能够从文件的输出中读取数据。xargs 一般是和管道一起使用。
格式 xargs [选项]... [命令 [初始参数]] 选项 -a #选项会忽略标准输入,因此在使用时确保不同时提供标准输入 -n N #每次最多使用 N 个参数 -d DELIM #指定输入参数的分隔符,默认为空格和换行符。 -I {} #用指定字符串 {} 替换输入数据中的每一行 -E flag flag #必须是一个以空格分隔的标志,当xargs分析到含有flag这个标志的时候就停止。 -r no-run-if-empty #当xargs的输入为空的时候则停止xargs,不用再去执行了 注意:linux命令格式一般为 命令 命令选项 参数 上一个命令的输出就是下一个命令的参数 这句话结合命令语法 应该知道输出的内容在下一个命令的 位置了吧。
默认xargs以空格为分隔符,可以通过-d来自定义分隔符 [root@rocky9 ~]# echo "ab cd ef g" | xargs ab cd ef g [root@rocky9 ~]# echo "nameXnameXnameXname" | xargs -dX name name name name [root@rocky9 ~]# echo "nameXnameXnameXname" | xargs nameXnameXnameXname -I 临时存储内容给一个对象,然后进行后续处理 [root@rocky9 ~]# xargs -a num.txt -n1 -I {} echo {}--bak 9--bak 8--bak 6--bak 8--bak 4--bak 7--bak 2--bak 1--bak -I的综合运用,转移文件并改名 [root@rocky9 ~]# ls *.txt a.txt b.txt num.txt test1.txt uniq.txt [root@rocky9 ~]# ls *.txt | xargs -n1 -I {} cp {} /tmp/{}-bak [root@rocky9 ~]# ls /tmp/*-bak /tmp/a.txt-bak /tmp/num.txt-bak /tmp/uniq.txt-bak /tmp/b.txt-bak /tmp/test1.txt-bak
ls * |xargs -n1 -I {} rename '{}' '{}.txt' {} #把当前目录下的所有文件名字后缀增加.txt
2三剑客
2.1sed&grep
2.1.1grep
-
grep 负责从数据源中检索对应的字符串,行过滤
格式 grep [选项] PATTERN [文件...] PATTERN:要搜索的模式,可以是字符串或正则表达式。 选项: -i #忽略大小写进行搜索 -v #反向匹配,显示不匹配模式的行。 -r|R #递归搜索目录及其子目录 -n #显示匹配行的行号 -l #只显示包含匹配模式的文件名 -c #只显示匹配的行数 -E #使用扩展正则表达式,允许使用更复杂的匹配模式。 -w #仅匹配整个单词。 ^key #以关键字开头 key$ #以关键字结尾 ^$ #匹配空行 -o #这个选项表示只输出匹配的部分,而不是整行。 -A #显示匹配行及后面多少行 -B #显示匹配行及前面多少行 -C #显示匹配行前后多少行 -P #选项用于启用Perl兼容的正则表达式(PCRE)支持 --color=auto #可以将找到的关键词部分加上颜色的显示
-
简单实践
常用命令选项必知必会 示例: grep -i root passwd #忽略大小写匹配包含root的行 grep -w ftp passwd #精确匹配ftp单词 grep -wo ftp passwd #打印匹配到的关键字ftp grep -n root passwd #打印匹配到root关键字的行好 grep -ni root passwd #忽略大小写匹配统计包含关键字root的行 grep -nic root passwd #忽略大小写匹配统计包含关键字root的行数 grep -i ^root passwd #忽略大小写匹配以root开头的行 grep bash$ passwd #匹配以bash结尾的行 grep -n ^$ passwd #匹配空行并打印行号 grep ^# /etc/vsftpd/vsftpd.conf #匹配以#号开头的行 grep -v ^# /etc/vsftpd/vsftpd.conf #匹配不以#号开头的行 grep -A 5 mail passwd #匹配包含mail关键字及其后5行 grep -B 5 mail passwd #匹配包含mail关键字及其前5行 grep -C 5 mail passwd #匹配包含mail关键字及其前后5行
-
技巧
grep -nir 关键字 /路径 #场景:快速检索,核心配置内容,修改配置。 grep -n xxx| cut -d ":" -f1 #获取行号
2.1.2sed基础
-
场景
shell脚本虽然功能很多,但是它最常用的功能还是处理文本文件,尤其是在正常的业务操作流程场景中,比如检查日志文件、读取配置、处理数据等现象,虽然我们能够使用echo、cat、<<、>>、|等符号实现文件内容的操作,但是整个过程有些繁琐。所以我们需要一种更为轻便的文本编辑工具,sed就是其中的一种。
-
简介
sed(Stream EDitor) 属于一种数据流式的行文件编辑工具。因为它编辑文件的时候,在内存中开辟一块额外的模式空间(pattern space),然后以行为单位读取文件内容到该空间中,接着sed命令处理该空间中的内容,默认在当前终端界面打印内容,然后清空模式空间内容,再来读取第二行内容,依次循环下去。
-
格式 sed [选项] '脚本' [文件...] sed [参数] '<匹配条件> [动作]' [文件名] 注意: 匹配条件和动作两侧有' 动作可以有多个,彼此间使用;隔开,比如 '2p;4p' 选项 参数为空 表示sed的操作效果,实际上不对文件进行编辑,缓存区所有信息都显示 -n #不输出模式空间内容到屏幕,即不自动打印所有内容 -e #基于命令实现对文件的多点编辑操作 -f #从指定文件中读取编辑文件的”匹配条件+动作” -r #支持使用扩展正则表达式 -i.bak #复制文件原内容到备份文件,然后对原文件编辑 -i #表示对文件进行编 -e #实现多次文件编辑动作
匹配条件分为两种:数字行号或者关键字匹配 数字行号: 空 #表示所有行 n #表示第n行 $ #表示末尾行 n,m #表示第n到m行内容 n,+m #表示第n到n+m行 ~步进 1~2 #表示奇数行 2~2 表示偶数行 关键字匹配格式: '/关键字/' 注意: 隔离符号 / 可以更换成 @、#、!等符号 根据情况使用,如果关键字和隔离符号有冲突,就更换成其他的符号即可。 /关键字1/,/关键字2/ 表示关键字1所在行到关键字2所在行之间的内容 n,/关键字2/ 表示从第n行到关键字2所在行之间的内容
动作详解 -a[\text] #在匹配到的内容下一行增加内容,支持\n实现多行追加 -i[\text] #在匹配到的内容当前行增加内容 -c[\text] #在匹配到的内容替换内容 -d|p #删除|打印匹配到的内容 -s #替换匹配到的内容 W /path/somefile #保存模式匹配的行至指定文件 r /path/somefile #读取指定文件的文本至模式空间中 = #为模式空间中的行打印行号 ! #模式空间中匹配行取反处理 注意: 上面的动作应该在参数为-i的时候使用,不然的话不会有效果
df | sed -n '/^\/dev\/sd/p' #打印磁盘信息 ip a show ens160 |sed -n '4p' |tr -s " "|cut -d " " -f3 | cut -d "/" -f1 #打印ip地址 root@rocky9:~ $ sed -n '/sed4/p' sed.txt nihao sed4 sed5 sed6 #内容匹配打印 root@rocky9:~ $ sed -n '1~2p' sed.txt nihao sed1 sed2 sed3 nihao sed7 sed8 sed9 #内容范围匹配打印(1~2p表示奇数打印) root@rocky9:~ $ sed -n '0~2p' sed.txt nihao sed4 sed5 sed6 #内容范围匹配打印(0~2p表示偶数打印) root@rocky9:~ $ sed -n -e '1p' -e '3p' sed.txt nihao sed1 sed2 sed3 nihao sed7 sed8 sed9 #实现多次文件编辑内容 #将文件操作命令输出到一个文件 root@rocky9:~ $ echo -e "1p\n3p" > d.txt #借助文件里面的命令实现文件编辑 root@rocky9:~ $ sed -n -f d.txt sed.txt nihao sed1 sed2 sed3 nihao sed7 sed8 sed9 root@rocky9:~ $ sed -n '2!p' sed.txt nihao sed1 sed2 sed3 nihao sed7 sed8 sed9 #取反显示 root@rocky9:~ $ sed -n '/sed4/=' sed.txt 2 #查看内容属于第几行
2.1.3sed替换
- sed的文本替换动作是使用频率最高的一种样式。它的基本表现样式如下:
格式
sed -i [替换格式] [文件名]
数据源 | sed -i [替换格式]
注意:替换命令的写法
's###' ---> 's#原内容##' ---> 's#原内容#替换后内容#'
隔离符号 / 可以更换成 @、#、!等符号
表现样式:
样式一:替换指定匹配的内容
sed -i '行号s#原内容#替换后内容#列号' [文件名]
echo "源数据" | sed -i '行号s#原内容#替换后内容#列号'
样式二:替换所有的内容
sed -i 's#原内容#替换后内容#g' [文件名]
echo "源数据" | sed -i '行号s#原内容#替换后内容#g'
样式三: 替换指定的内容
sed -i '行号s#原内容#&新增信息#列号' [文件名]
- 这里的&符号代表源内容,实现的效果是 '原内容+新内容'
-
实践
-
替换每行首个匹配内容
格式:sed -i 's#原内容#替换后内容#' 文件名 替换每行的第一个sed为SED root@rocky9:~ $ sed -i 's#sed#SED#' sed.txt
-
替换全部匹配内容
格式:sed -i 's#原内容#替换后内容#g' 文件名 替换全部sed为des root@rocky9:~ $ sed -i 's#sed#SED#g' sed.txt root@rocky9:~ $ sed 'y/SED/sed/' sed.txt
-
指定行号替换首个匹配内容
格式:sed -i '行号s#原内容#替换后内容#' 文件名 替换第2行的首个SED为sed root@rocky9:~ $ sed -i '2s#SED#sed#' sed.txt
-
首行指定列号替换匹配内容
格式:sed -i 's#原内容#替换后内容#列号' 文件名 替换每行的第2个SED为sed root@rocky9:~ $ sed -i 's#SED#sed#2' sed.txt
-
指定行号列号匹配内容
格式:sed -i '行号s#原内容#替换后内容#列号' 文件名 替换第3行的第2个SED为sed root@rocky9:~ $ sed -i '3s#SED#sed#2' sed.txt
-
综合实践
借助正则的分组功能实现ip地址获取 [root@rocky9 ~]# ifconfig eth0 | sed -n '2p' | sed -r 's#.*inet (.*) net.*#\1#' [root@rocky9 ~]# ifconfig eth0 | sed -n '2p' | sed -r 's#.*inet ##' | sed -r 's# net.*##' 借助正则的分组功能实现信息的精确获取 [root@rocky9 ~]# echo '/etc/sysconfig/network' | sed -r 's#(.*\/)([^/]+\/? $)#\2#' network [root@rocky9 ~]# echo '/etc/sysconfig/network' | sed -r 's#(.*\/)([^/]+\/? $)#\1#' /etc/sysconfig/
-
2.1.4增加操作
- 基本语法
作用:
在指定行号的下一行增加内容
格式:
sed -i '行号a\增加的内容' 文件名
注意:
如果增加多行,可以在行号位置写个范围值,彼此间使用逗号隔开,例如
sed -i '1,3a\增加内容' 文件名
- 插入实践
指定行号增加内容
root@rocky9:~ $ sed -i '2a\wwwwwwww' sed.txt
#在第二行的下一行插入
root@rocky9:~ $ sed -i '1,3a\bbbbbbbbbb' sed.txt
#在第一行和第三行的下一行插入
- 插入实践
作用:
在指定行号的当行增加内容
格式:
sed -i '行号i\增加的内容' 文件名
注意:
如果增加多行,可以在行号位置写个范围值,彼此间使用逗号隔开,例如
sed -i '1,3i\增加内容' 文件名
-
基于行号实践
指定行号增加内容 root@rocky9:~ $ sed -i '5i\hellllllllll' sed.txt #在第五行写入hellllllllll 指定1~3每行都增加内容 root@rocky9:~ $ sed -i '2,6i\***********' sed.txt #在第二行和第六行写入**********
2.1.5删除替换
-
基本语法
作用: 指定行号删除 格式: sed -i '行号d' 文件名 注意: 如果删除多行,可以在行号位置多写几个行号,彼此间使用逗号隔开,例如 sed -i '1,3d' 文件名
-
基于行号实践
删除第4行内容 root@rocky9:~ $ sed -i '4d' sed.txt 删除多行(1-6行)内容 root@rocky9:~ $ sed -i '1,6d' sed.txt
-
基本语法
作用: 指定行号进行整行替换 格式: sed -i '行号c\内容' 文件名 注意: 如果替换多行,可以在行号位置多写几个行号,彼此间使用逗号隔开,例如 sed -i '1,3c\内容' 文件名
基于行号实践
替换第3行内容 root@rocky9:~ $ sed -i '3c\1111111111' sed.txt #替换第三行的内容为1111111111 指定1~3行都替换成一行内容 root@rocky9:~ $ sed -i '1,3c\ ' sed.txt #替换1-3行的内容为" "
2.1.6加载保存
-
加载实践
基本语法
作用: 加载文件内容到指定行号的位置 格式: sed -i '行号r 文件名1' 文件名 注意: 如果在多行位置加载,可以在行号位置多写几个行号,彼此间使用逗号隔开,例如 sed -i '1,3r 文件名1' 文件名
基于行号实践
加载第3行内容 root@rocky9:~ $ sed -i '2r sed.txt' sed.txt #读sed.txt这个文件在sed.txt中的第二行插入 制定内容文件,加载到2-4行下面 root@rocky9:~ $ sed -i '2,4r file1' sed.txt #在源文件的2、3、4行下面分别插入file1文件内容
-
保存实践
基本语法
作用: 指定行号保存到其他位置 格式: sed -i '行号w 要保存到的文件名' 文件名 注意: 如果多行保存,可以在行号位置多写几个行号,彼此间使用逗号隔开,例如 sed -i '1,3w 文件名' 文件名 文件名已存在,则会覆盖式增加
基于行号实践 保存第3行内容 root@rocky9:~ $ sed -i '2w file2' sed.txt #保存第二行到file2 指定1~4行内容保存到一个文件中 root@rocky9:~ $ sed -i '1,4w sed1.txt' sed.txt #保存1-4行的内容到sed1.txt
2.1.7匹配进阶
基础知识
-
内容匹配: '/关键字内容/' 注意: 隔离符号 / 可以更换成 @、#、!等符号 根据情况使用,如果关键字和隔离符号有冲突,就更换成其他的符号即可。 /关键字1/,/关键字2/ 表示关键字1所在行到关键字2所在行之间的内容 n,/关键字2/ 表示从第n行到关键字2所在行之间的内容 /关键字1/,n, 表示从关键字1所在行到第n行之间的内容 /关键字1/,+n, 表示从关键字1所在行到(所在行+n行)之间的内容
匹配显示
查看匹配内容 root@rocky9:~ $ sed -n '/then/p' .bashrc #匹配显示.bashrc中包含then的行 匹配内容间的多行信息 root@rocky9:~ $ sed -n '/then/,/User/p' .bashrc #匹配.bashrc中的包含then的第一行到包含User的最后一行 查看匹配内容到第6行的内容 root@rocky9:~ $ sed -n '/bin/,6p' .bashrc #查看匹配到bin的六行记录 查看第1行到匹配行的内容 root@rocky9:~ $ sed -n '1,/if/p' .bashrc #查看第一行到匹配行的内容 查看匹配内容和下面三行的内容 root@rocky9:~ $ sed -n '/if/,+3p' .bashrc #查看.bashrc文件中第一个匹配到if行到最后一个匹配到if的行下面三行 通过 !p 去除空行匹配 root@rocky9:~ $ sed -n '/^&/!p' .bashrc #去除所有空行 借助分组功能,实现多信息的剔除 [root@rocky9 ~]# sed -rn '/^(#|$)/!p' nginx.conf
-
分组信息显示
获取制定文件所在的路径信息 [root@rocky9 ~]# echo "/etc/sysconfig/network" |sed -r 's#(^/.*/)([^/]+/?)#\1#' /etc/sysconfig/ 获取制定文件名称 [root@rocky9 ~]# echo "/etc/sysconfig/network" |sed -r 's#(^/.*/)([^/]+/?)#\2#' network 获取ip地址 [root@rocky9 ~]# ifconfig eth0 |sed -nr "2s/[^0-9]+([0-9.]+).*/\1/p" 10.0.0.12 获取MAC地址 [root@rocky9 ~]# ifconfig eth0 |sed -nr "4s/[^0-9]+([0-Z:]+).*/\1/p" 00:0c:29:23:23:8c 正则解读: [^0-9]+: 匹配一个或多个非数字字符。 ([0-Z:]+): 这是一个捕获组,表示0-9,a-Z,以及: 这些符号,但0-Z并不是一个有效的字符范围。 如果你的意图是匹配数字、大写字母和冒号,[0-Z:]应该使用[0-9A-Z:]。 .*: 匹配任意数量的任意字符(除了换行符)。 \1: 表示替换为第一个捕获组的内容。
2.1.8文件处理
-
多点操作
我们可以借助 '动作1;动作2' 或者 -e '动作1' -e '动作2' 的方式实现多操作的并行实施
内容的过滤编辑
不显示所有空行和注释信息 [root@rocky9 ~]# sed '/^#/d;/^$/d' nginx.conf worker_processes 1; http { sendfile on; keepalive_timeout 65; server { listen 8000; server_name localhost; location / { root html; index index.html index.htm; } } } 先剔除空行,然后不显示所有包含注释的信息 [root@rocky9 ~]# sed -rn '/^$/d;/^[[:space:]]*#/!p' nginx.conf worker_processes 1; http { sendfile on; keepalive_timeout 65; server { listen 8000; server_name localhost; location / { root html; index index.html index.htm; } } }
借助于 i.bak 方式对有效信息进行过滤
编辑文件的时候,原内容备份到一个额外的文件 [root@rocky9 ~]# sed -i.bak '/^#/d;/^$/d' nginx.conf [root@rocky9 ~]# cat nginx.conf worker_processes 1; http { sendfile on; keepalive_timeout 65; server { listen 8000; server_name localhost; location / { root html; index index.html index.htm; } } } [root@rocky9 ~]# grep '#' nginx.conf.bak #user nobody;
增改实践
借助于&符号实现内容的扩充式更改编辑
查看原内容 [root@rocky9 ~]# head -n 1 /etc/passwd root:x:0:0:root:/root:/bin/bash 对原内容进行扩充替换 [root@rocky9 ~]# head -n 1 /etc/passwd | sed -n 's/root/&user/1p' rootuser:x:0:0:root:/root:/bin/bash [root@rocky9 ~]# head -n 1 /etc/passwd | sed -n 's/root/&user/gp' rootuser:x:0:0:rootuser:/rootuser:/bin/bash
借助于s实现内容的替换式更改编辑
获取没有被注释的信息 [root@rocky9 ~]# sed -n '/^#/!p' /etc/fstab UUID=5583bd7c-cc9f-4e19-b453-c224102f3ed5 / xfs defaults 0 0 UUID=cbd246cd-1df8-4fe7-9040-823cd0978837 /boot xfs defaults 0 0 将注释的信息进行替换 [root@rocky9 ~]# sed -rn '/^#/!s@^@#@p' /etc/fstab # #UUID=5583bd7c-cc9f-4e19-b453-c224102f3ed5 / xfs defaults 0 0 #UUID=cbd246cd-1df8-4fe7-9040-823cd0978837 /boot xfs defaults 0 0
借助于 i|a 对文件进行 插入|追加 式更改编辑
基于内容匹配相关信息并打印 [root@rocky9 ~]# sed -n '/listen/p' nginx.conf worker_processes 1; http { sendfile on; keepalive_timeout 65; server { listen 8000; server_name localhost; location / { root html; index index.html index.htm; } } } 基于内容匹配追加1行内容 [root@rocky9 ~]# sed '/listen/a\\tlisten\t\t80;' nginx.conf worker_processes 1; http { sendfile on; keepalive_timeout 65; server { listen 8000; listen 80; server_name localhost; location / { root html; index index.html index.htm; } } } 基于内容匹配插入2行内容 -- 借助于\n的换行功能,将1行变成两行 [root@rocky9 ~]# sed '/listen/i\\tlisten\t\t80;\n\tlisten\t\t8080;' nginx.conf worker_processes 1; http { sendfile on; keepalive_timeout 65; server { listen 80; listen 8080; listen 8000; server_name localhost; location / { root html; index index.html index.htm; } } }
借助于 环境变量和s|c 对文件进行 修改|替换 式更改编辑
定制环境变量 [root@rocky9 ~]# port=8080 使用多点修改 [root@rocky9 ~]# sed -r -e "s/listen.*;/listen\t$port;/" -e '/server_name/c \\tserver_name '$(hostname):$port';' nginx.conf worker_processes 1; http { sendfile on; keepalive_timeout 65; server { listen 8080; server_name localhost:8080; location / { root html; index index.html index.htm; } } } 注意: 这里涉及到环境变量的解读,千万不要被单引号转义了
2.2AWK基础
2.2.1awk基础
内存使用率的统计步骤
1) 通过free -m提取出内存总量,赋值给变量 memory_totle
2)通过free -m提取出n内存使用量,赋值给变量memory_use
3)通过数学运算计算内存使用率
需要执行多步才能得到内存使用率,那么有没有一个命令能够集过滤、提取、运算为一体呢?当然,就是
今天我要给大家介绍的命令:awk
- awk简介
awk全称 Aho Weinberger Kernighan报告生成器,awk的三个字母是来自于三个作者的首字母。它
是一个功能非常强大的文档编辑工具,它不仅能以行为单位还能以列为单位处理文件,并且还具有格式化文本
输出功能。目前它受自由软件基金会(FSF)进行开发和维护,通常也称它为 GNU AWK,AWK有多种版本:
AWK:原先来源于 AT & T 实验室的的AWK
NAWK:New awk,AT & T 实验室的AWK的升级版
GAWK:即GNU AWK。所有的GNU/Linux发布版都自带GAWK,它与AWK和NAWK完全兼容
原理解读
awk 认为文件中的每一行是一条记录,记录与记录的分隔符为换行符,每一列是一个字段 字段与字段的
分隔符默认是一个或多个空格或tab制表符.
awk的工作方式是逐行读取文本数据,将每一行数据视为一条记录(record)每条记录以字段分隔符分成若干字段,然后输出各个字段的值.然后以查找匹配某个特定模式的文本行,并对这些文本执行制定动作。
- 基本格式
格式:
awk [参数] '[动作]' [文件名]
awk [参数] –f 动作文件 var=value [文件名]
awk [参数] 'BEGIN段 [动作] END段' [文件名]
注意:
动作的格式 '匹配条件{打印动作}'
参数
-F 指定列的分隔符,默认一行数据的列分隔符是空格
-f file 指定读取程序的文件名
-v var=value 自定义变量
awk程序运行优先级是:
1 BEGIN: 在开始处理数据流之前执行,可选项
2 动作: 如何处理数据流,必选项
3 END: 处理完数据流后执行,可选项
常见动作
print 显示内容
$0 显示当前行所有内容
$n 显示当前行的第n列内容,如果存在多个$n,它们之间使用逗号(,)隔开注意:
如果打印的内容是变量,则无需在变量两侧加上双引号,其他的都应该加双引号
- 其他功能
printf 格式化显示内容
printf [-v var] format [item1,item2,...]
注意:
printf输出需要指定换行符号,format的格式必须与后面item对应
常见格式:
%c 显示字符的ASCII码 %d|i 显示十进制整数 %e|E 显示科学计数法数值
%f 显示浮点数 %s 显示字符串 %u 显示无符号整数
%% 显示%本身
修饰符:
%#[.#] 第一个#控制显示宽度,第二个#表示小数点后的精度,例如%3.1f
%- 左对齐,%-15s
%+ 显示数值的正负符号,%+d
常见内置变量
FILENAME 当前输入文件的文件名,该变量是只读的
NR 指定显示行的行号
FNR 多文件时候,分别计数
NF 表示字段数量
OFS 输出格式的列分隔符,缺省是空格
FS 输入文件的列分隔符,缺省是连续的空格和Tab
RS 输入记录分隔符,指定输入时的换行符,原换行符($)仍有效
ORS 输出记录分隔符,输出时用指定符号代替换行符
ARGC|ARGV[n] 获取命令的参数个数|参数内容
2.2.2基础语法
-
字段提取
字段提取:提取一个文本中的一列数据并打印输出,它提供了相关的内置变量。 $0 表示整行文本 $1 表示文本行中的第一个数据字段 $2 表示文本行中的第二个数据字段 $N 表示文本行中的第N个数据字段 $NF 表示文本行中的最后一个数据字段 NR 代表行的行号,在动作外部表示特定行 注意: 如果打印多列信息,需要使用逗号隔开,否则是内容合并
-
定制查看
awk默认的信息查看是以空格作为列分隔符的,而对于非空格作为分隔符的内容,我们需要借助于专门的语法实现信息的分割,这里主要用到以下知识: 常见参数: -F #指定列的分隔符,默认一行数据的列分隔符是空格 常见的内置变量 FS 输入文件的列分隔符,缺省是连续的空格和Tab RS 输入记录分隔符,指定输入时的换行符,原换行符($)仍有效 注意: 一般情况下,在输出信息之前进行格式的调整,需要在BEGIN{}部分设定
2.2.3显示语法
基础知识
awk支持格式化输出相关信息。它主要依赖两种方法:
属性方法
OFS 输出格式的列分隔符,缺省是空格
ORS 输出记录分隔符,输出时用指定符号代替换行符
print方法
printf [-v var] format [item1,item2,...]
注意:
printf输出需要指定换行符号,format的格式必须与后面item对应
常见格式:
%c 显示字符的ASCII码 %d|i 显示十进制整数
%e|E 显示科学计数法数值 %u 显示无符号整数
%f 显示浮点数 %s 显示字符串
%% 显示%本身
修饰符:
%#[.#] 第一个#控制显示宽度,第二个#表示小数点后的精度,例如%3.1f
%- 左对齐,%-15s
%+ 显示数值的正负符号,%+d
2.2.4优先级
-
简介
awk为了体现程序的逻辑顺序,划分了三个代码段。 格式: BEGIN[]: #读入第一行文本之前执行的语句,一般用来初始化操作 {}: #逐行处理的执行命令 END[]: #处理完最后以行文本后执行,一般用来处理输出结果
-
实例
root@rocky9:~ $ awk 'BEGIN{printf "----------------------\n|%-3s|%2s|%2s|%2s|\n----------------------\n","姓名","语文","数学","英语";} NR>=1{printf "|%-3s|%4d|%4d|%4d|\n",$1,$2,$3,$4}END{printf "----------------------\n学 生总数:%2d\n",NR}' cou.txt ---------------------- |姓名 |语文|数学|英语| ---------------------- |张三 | 100| 56| 99| |李四 | 90| 68| 89| |王五 | 50| 78| 67| |赵六 | 80| 99| 89| ---------------------- 学生总数: 4
2.2.5变量实践
awk所支持的变量主要有两种类型:内置变量和自定义变量
- 变量类型:
内置变量
NR #指定显示行的行号
NF #表示字段数量
OFS #输出格式的列分隔符,缺省是空格
FS #输入文件的列分隔符,缺省是连续的空格和Tab
自定义变量
-v var=value
它可以在 命令行、BEGIN、{}、END 等位置进行使用
root@rocky9:~ $ echo /etc/sysconfig/network-scripts/ifcfg-eth0 | awk -F / '{print $(NF-1)}'
network-scripts
#快速获取ip地址
root@rocky9:~ $ ip add show ens160 | awk NR==4'{print $0}' | awk '{print $2}' | awk -F"/" '{print $1}'
10.0.0.11
#快速获取行号
root@rocky9:~ $ awk -F: 'END{print NR}' /etc/passwd
26
#ARGC 获取命令行参数的个数,包括awk命令
[root@rocky9 ~]# awk 'NR==1 {print ARGC }' awk.txt
2
#ARGV:将命令行所有参数放到一个数组中,ARGV[下标] 获取所有参数
[root@rocky9 ~]# awk 'NR==1 {print ARGV[0] }' awk.txt
awk
[root@rocky9 ~]# awk 'NR==1 {print ARGV[1] }' awk.txt
awk.txt
#自定义变量
[root@rocky9 ~]# awk -v name='shuji' 'BEGIN{print name}'
shuji
2.2.6赋值运算
awk的表达式包括很多种类,常见的表达式有:
算术操作符:+ - * / ^ %
赋值操作符:= += -= /= ++ -- %= ^=
比较操作符:== != > >= < <=
模式匹配符:~ 左边是否与右边匹配包含,!~ 是否不匹配
逻辑操作符:与&&、或||、非!
root@rocky9:~ $ echo | awk '{i=10;print i+=1}'
11
root@rocky9:~ $ echo | awk '{i=10;print i++}'
10
root@rocky9:~ $ echo | awk '{i=10;print i++1}'
101
root@rocky9:~ $ echo | awk '{i=10;print i++,i}'
10 11
root@rocky9:~ $ echo | awk '{i=10;print ++i,i}'
11 11
root@rocky9:~ $ echo | awk '{i=10;print --i,i}'
9 9
root@rocky9:~ $ echo | awk '{i=10;print i--,i}'
10 9
在BEGIN段是可以的,由于END段主要是收尾的信息显示,所以基本不做计算层次的功能
root@rocky9:~ $ echo | awk 'BEGIN{i=10;print i+=1}'
11
变量赋值-拓展【真假非】
root@rocky9:~ $ awk -v n=0 'n++' awk.txt
nihao awk4 awk5 awk6
nihao awk7 awk8 awk9
root@rocky9:~ $ awk -v n=0 '++n' awk.txt
nihao awk1 awk2 awk3
nihao awk4 awk5 awk6
nihao awk7 awk8 awk9
root@rocky9:~ $ awk -v n=0 '!n++' awk.txt
nihao awk1 awk2 awk3
结果显示:
-v n=0 在 awk 程序开始执行之前设置一个变量,并将其初始值设为 0。
n++ 是后增量操作
当 awk 开始处理第一行时,变量 n 的值为 0,因此 !n(即 !0)的值为 1 因为在逻辑上,0 被视为假,而 !0 则是真,即 1。因此,第一行会被打印出来。
当处理第二行时,由于 n++ 的操作,n 的值变为 1。此时,!n(即 !1)的值为 0(
因为在逻辑上,1 被视为真,而 !1 则是假,即 0。因此,第二行及之后的行不会被打印。
当递增与!同时存在的时候,!优先生效
- 数组赋值
root@rocky9:~ $ awk 'BEGIN{arr[0]=100;print arr[0]}'
100
BEGIN 块在处理输入数据之前执行,适用于初始化操作。
arr[0]=100 将数组 arr 的第一个元素(索引为 0)设置为 100。
print arr[0] 输出数组 arr 中索引为 0 的元素的值,即 100。
2.2.7数学运算
所谓的数学运算,其实就是我们平常所说的二元运算,常见的运算符号有:
+ - * / ^ %
root@rocky9:~ $ awk 'BEGIN{print 100+3}'
103
root@rocky9:~ $ awk 'BEGIN{print 100-3}'
97
root@rocky9:~ $ awk 'BEGIN{print 100*3}'
300
root@rocky9:~ $ awk 'BEGIN{print 100/3}'
33.3333
root@rocky9:~ $ awk 'BEGIN{print 100**3}'
1000000
root@rocky9:~ $ awk 'BEGIN{print 100%3}'
1
root@rocky9:~ $ awk 'BEGIN{printf "---------------------------\n|%-3s|%2s|%2s|%2s|%2s|\n---------------------------\n","姓名","语文","数学","历史","总分";yu=0;shu=0;li=0;total} NR>=1 {yu=$2+yu;shu=$3+shu;li=$4+li;total=$2+$3+$4; printf "|%-3s|%4d|%4d|%4d|%4d|\n",$1,$2,$3,$4,$2+$3+$4} END{printf "---------------------------\n|%-3s|%4d|%4d|%4d|%4d|\n学生总数总: %2d\n","合计",yu,shu,li,total,NR}' cou.txt
---------------------------
|姓名 |语文|数学|历史|总分|
---------------------------
|张三 | 100| 56| 99| 255|
|李四 | 90| 68| 89| 247|
|王五 | 50| 78| 67| 195|
|赵六 | 80| 99| 89| 268|
---------------------------
|合计 | 320| 301| 344| 268|
学生总数总: 4
2.2.8逻辑运算
所谓的逻辑运算,其实指的就是 与或非的操作。基本语法格式如下:
与&& - 并且关系
或|| - 或者关系
非! - 取反关系
2.2.9匹配运算
注意事项:
如果没有指定,为空模式,匹配每一行
如果指定”/匹配条件/”,则表示仅处理能够匹配到的内容
如果指定关系表达式,只有结果为真的情况下,才会被处理
真:结果为非0值,非空字符串,空格也是真
假:结果为空字符串或0值,数值不用加””
内容匹配
root@rocky9:~ $ awk -F ':' '$1 ~ "^ro" {print $0}' /etc/passwd
#root:x:0:0:root:/root:/bin/bash
root@rocky9:~ $ awk -F ':' '$1 ~ "ftp" {print $0}' /etc/passwd
#ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
root@rocky9:~ $ awk -F ':' '$1 ~ "^[a-d]" {print $0}' /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
#dbus:x:81:81:System message bus:/:/sbin/nologin
#chrony:x:996:994:chrony system user:/var/lib/chrony:/sbin/nologin
内容不匹配
root@rocky9:~ $ awk -F ':' '$1 !~ "^[a-d]" {print $0}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
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:65534:65534:Kernel Overflow User:/:/sbin/nologin
systemd-coredump:x:999:997:systemd Core Dumper:/:/sbin/nologin
polkitd:x:998:996:User for polkitd:/:/sbin/nologin
sssd:x:997:995:User for sssd:/:/sbin/nologin
tss:x:59:59:Account used for TPM access:/:/usr/sbin/nologin
sshd:x:74:74:Privilege-separated SSH:/usr/share/empty.sshd:/usr/sbin/nologin
hzk:x:1000:1000:hzk:/home/hzk:/bin/bash
nginx:x:995:992:Nginx web server:/var/lib/nginx:/sbin/nologin
magedu:x:1002:1002::/home/magedu:/bin/bash
postfix:x:89:89::/var/spool/postfix:/sbin/nologin
kk1:x:1003:1003:nihao to hzk:/home/kk1:/bin/bash
kong:x:1004:1004::/home/kong:/bin/bash
文件规整
root@rocky9:~ $ awk '/^[ \t]*/{print NR"--->"$1}' zhengli.txt
/^[ \t]*/: 这个模式匹配以任意数量的空格或制表符开头的行。^ 表示行的开头,[ \t]* 表示零个或多个空格或制表符。
{print NR "--->" $1}: 对于匹配的每一行,print 语句会输出当前行号(NR)和该行的第一个字段($1),中间用 "--->" 分隔。
多值匹配打印
oot@rocky9:~ $ awk 'i=1;j=1{print $1,$3}' awk.txt
oot@rocky9:~ $ awk 'i=1{print $0};j=1{print $1,$3}' awk.txt
命令解析:
i=1;j=1{print $1,$3} 是两条命令
i=1; 虽然后面没有添加{},但是默认是 {print $0} 打印整行
非零真值匹配
root@rocky9:~ $ awk -v n=0 '++n' awk.txt
2.2.10内置函数
数值类内置函数
int(expr) 截断为整数:int(123.45)和int("123abc")都返回123,int("a123")返回0
sqrt(expr) 返回平方根
rand() 返回[0,1)之间的随机数,默认使用srand(1)作为种子值
srand([expr]) 设置rand()种子值,省略参数时将取当前时间的epoch值(精确到秒的epoch)作为种子值
字符串类内置函数
sprintf(format, expression1, ...):返回格式化后的字符串
length():返回字符串字符数量、数组元素数量、或数值转换为字符串后的字符数量
strtonum(str):将字符串转换为十进制数值
如果str以0开头,则将其识别为8进制
如果str以0x或0X开头,则将其识别为16进制
tolower(str):转换为小写
toupper(str):转换为大写
index(str,substr):从str中搜索substr(子串),返回搜索到的索引位置,搜索不到则返回0
数据操作内置函数
substr(string,start[,length]):从string中截取子串
split(string, array [, fieldsep [, seps ] ]):将字符串分割后保存到数组array中
match(string,reg[,arr]):使用reg正则规则匹配string信息,默认返回匹配的索引,可以将内容存到数组
index查找子字符串的位置
root@rocky9:~ $ awk 'BEGIN{v="ldshgkhsafihasdkfddsf";print index(v,"hs")}'
7
substr字符串截取
root@rocky9:~ $ awk 'BEGIN{v="ldshgkhsafihasdkfddsf";print substr(v,3)}'
shgkhsafihasdkfddsf
root@rocky9:~ $ awk 'BEGIN{v="ldshgkhsafihasdkfddsf";print substr(v,3,3)}'
shg
split切割字符串
[root@rocky9 ~]# awk 'BEGIN{split("abc-def-gho-pq",arr,"-",seps); print
length(arr), arr[3], seps[1]}'
4 gho -
[root@rocky9 ~]# awk 'BEGIN{split("abcde",arr,"-");print arr[1]}'
abcde
root@rocky9:~ $ echo "04:06:20" | awk '{split($0,a,":");print a[1],a[2],a[3]}'
04 06 20
match字符串匹配
[root@rocky9 ~]# awk 'BEGIN{str="safdsajfkdsajlfjdsl";print match(str,"j.*s")}'
7
[root@rocky9 ~]# awk 'BEGIN{str="safdsajfkdsajlfjdsl";match(str,"j.*s",arry);print arry[0]}'
jfkdsajlfjds
时间类内置函数
mktime("YYYY MM DD HH mm SS [DST]"):构建一个时间,构建失败则返回-1
systime():返回当前系统时间点,返回的是秒级epoch值
strftime([format [, timestamp [, utc-flag] ] ]):将时间格式转换为字符串
数据类型相关内置函数:
isarray(var):测试var是否是数组,返回1(是数组)或0(不是数组)
typeof(var):返回var的数据类型,有以下可能的值:
“array”:是一个数组
“regexp”:是一个真正表达式类型,强正则字面量才算是正则类型,如@/a.*ef/
“number”:是一个number
“string”:是一个string
“strnum”:是一个strnum,参考strnum类型
“unassigned”:曾引用过,但未赋值,例如”print f;print typeof(f)”
“untyped”:从未引用过,也从未赋值过
令解析:
i=1;j=1{print $1,$3} 是两条命令
i=1; 虽然后面没有添加{},但是默认是 {print $0} 打印整行
非零真值匹配
root@rocky9:~ $ awk -v n=0 ‘++n’ awk.txt
### 2.2.10内置函数
数值类内置函数
int(expr) 截断为整数:int(123.45)和int(“123abc”)都返回123,int(“a123”)返回0
sqrt(expr) 返回平方根
rand() 返回[0,1)之间的随机数,默认使用srand(1)作为种子值
srand([expr]) 设置rand()种子值,省略参数时将取当前时间的epoch值(精确到秒的epoch)作为种子值
字符串类内置函数
sprintf(format, expression1, …):返回格式化后的字符串
length():返回字符串字符数量、数组元素数量、或数值转换为字符串后的字符数量
strtonum(str):将字符串转换为十进制数值
如果str以0开头,则将其识别为8进制
如果str以0x或0X开头,则将其识别为16进制
tolower(str):转换为小写
toupper(str):转换为大写
index(str,substr):从str中搜索substr(子串),返回搜索到的索引位置,搜索不到则返回0
数据操作内置函数
substr(string,start[,length]):从string中截取子串
split(string, array [, fieldsep [, seps ] ]):将字符串分割后保存到数组array中
match(string,reg[,arr]):使用reg正则规则匹配string信息,默认返回匹配的索引,可以将内容存到数组
index查找子字符串的位置
root@rocky9:~ $ awk ‘BEGIN{v=“ldshgkhsafihasdkfddsf”;print index(v,“hs”)}’
7
substr字符串截取
root@rocky9:~ $ awk ‘BEGIN{v=“ldshgkhsafihasdkfddsf”;print substr(v,3)}’
shgkhsafihasdkfddsf
root@rocky9:~ $ awk ‘BEGIN{v=“ldshgkhsafihasdkfddsf”;print substr(v,3,3)}’
shg
split切割字符串
[root@rocky9 ~]# awk ‘BEGIN{split(“abc-def-gho-pq”,arr,“-”,seps); print
length(arr), arr[3], seps[1]}’
4 gho -
[root@rocky9 ~]# awk ‘BEGIN{split(“abcde”,arr,“-”);print arr[1]}’
abcde
root@rocky9:~ $ echo “04:06:20” | awk ‘{split($0,a,“:”);print a[1],a[2],a[3]}’
04 06 20
match字符串匹配
[root@rocky9 ~]# awk ‘BEGIN{str=“safdsajfkdsajlfjdsl”;print match(str,“j.*s”)}’
7
[root@rocky9 ~]# awk ‘BEGIN{str=“safdsajfkdsajlfjdsl”;match(str,“j.*s”,arry);print arry[0]}’
jfkdsajlfjds
时间类内置函数
mktime(“YYYY MM DD HH mm SS [DST]”):构建一个时间,构建失败则返回-1
systime():返回当前系统时间点,返回的是秒级epoch值
strftime([format [, timestamp [, utc-flag] ] ]):将时间格式转换为字符串
数据类型相关内置函数:
isarray(var):测试var是否是数组,返回1(是数组)或0(不是数组)
typeof(var):返回var的数据类型,有以下可能的值:
“array”:是一个数组
“regexp”:是一个真正表达式类型,强正则字面量才算是正则类型,如@/a.*ef/
“number”:是一个number
“string”:是一个string
“strnum”:是一个strnum,参考strnum类型
“unassigned”:曾引用过,但未赋值,例如”print f;print typeof(f)”
“untyped”:从未引用过,也从未赋值过