1 文本处理

1.1 文本处理

1.1.1 vi & vim

进入文件:
vim file +N   #进入文件的N行
vim file +/keyword  #进入文件的N行

检索内容	
/keyword    #向后检索
?keyword   #向前检索

其他命令:
r filename  读文件内容到当前文件中
w filename  将当前文件内容写入另一个文件
r!command   读入命令的输出

范围帅选:
:5,7   第5到第7行
:/key1/,/key2/  key1 到 key2 的范围

内容替换:vim的所有替换能力 都可以 通过sed简单实现
从全文替换
  :%s/原内容/替换后内容/g     
从当前行到最后一行进行替换
  :,$s/原内容/替换后内容/g  (, 当前行,$ 末尾行)
正则匹配内容进行全文替换
  :/关键字/,$s/原内容/替换后内容/g
从第3到第6行内容进行替换
  :3,6s/原内容/替换后内容/g

属性定制
通过  .vimrc 文件定制,以后直接用,不再编辑了
手工常用属性
:set nu  | nonu   显示行号
:set paste | nopaste   保留黏贴内容之前的格式
:set cul | nocul     显示行辅助参考线
:set autoindent|set ai    启用自动缩进
:set hlsearch   高亮显示搜索结果
:set fileformat=dos|set ff=dos   启用windows文件格式
:set fileformat=unix|set ff=unix   启用unix文件格式
:set key=password     加密文档               
:set key=      取消加密    
:set background=dark " 设置背景色为深色

1.1.8 光标跳转

常用属性

行首行尾跳转:

^      跳转至行首的第一个非空白字符
0      跳转至行首         
$      跳转至行尾

行间移动:

NG|:N    跳转至指定行,N表示正整数,比如 10G,或在扩展命令模式下:10,都表示跳转到第10行
G        最后一行        
gg|1G    第一行

单词间跳转

w     下一个单词的词首          
e      当前或下一单词的词尾         
b       当前或前一个单词的词首        
Nw|Ne|Nb   一次跳N个单词

个人常用:

ctrl+v 选中多行的同一列,一般行首,
再按shift+i,光标自动跳到选择的第一行首,然后可以进行向前,向后的缩进,
完成后按ESC,之前选中的下面的行也会照样行动,而且保留它们自己原本的缩进,调整脚本常用。
向前缩进可以选中左边所有空白处然后d就是删除了。


1.2 vim高阶

1.2.1 专属配置

vimrc文件

一般有两种形态:系统级别和用户级别。- 系统级别的vimrc文件在 /etc/路径下,不是隐藏文件。- 用户级别的.vimrc 文件位于 $HOME/ 目录下,是一个隐藏文件。

一般情况下,该文件是不存在的,需要手工创建。


简单实践

定制一个通用的vimrc配置,让我们在编辑所有 .sh 后缀文件的时候,自动添加文件

[root@rocky9 ~]# cat .vimrc
 autocmd BufNewFile *.sh exec ":call ShellTitle()"
 function  ShellTitle()
 call append(0,"#!/bin/bash")
 call append(1,"# *************************************")
 call append(2,"# * 功能: Shell脚本模板")
 call append(3,"# * 作者: 王树森")
 call append(4,"# * 联系: wangshusen@sswang.com")
 call append(5,"# * 版本: ".strftime("%Y-%m-%d"))
 call append(6,"# *************************************")
 endfunction
 set tabstop=2 
set shiftwidth=2
 set expandtab  
set number
 set autoindent
 set cursorline
 set showmatch
 syntax on
 set background=dark 
colorscheme desert

效果展示:

============================================================================

5-文本处理工具和正则表达式_分隔符

=============================================================================


1.2.2 可视化模式

v(小写)        面向字符
V(大写)        面向整行      
ctrl-v(小写)   面向块


1.2.3 多文件模式

多文件切割

vim -o|-O FILE1 FILE2 ...
-o        水平或上下分割
-O        垂直或左右分割(vim only)          
:wqall    退出          
Ctrl+w, Arrow     在窗口间切换,Arrow 表示方向键

多窗口切换

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   在窗口间切换,Arrow 表示方向键



1.3 内容处理

1.3.1 文件查看

cat 命令
-n 或 --number:由1开始对所有输出的行数编号12。
-b 或 --number-nonblank:只为非空行编号,空白行不编号12。
-s 或 --squeeze-blank:合并多个连续空行为一行12。
-E 或 --show-ends:在每行末尾显示$字符,以指示行的结束12。
-T 或 --show-tabs:将制表符显示为^I字符23。
-A 或 --show-all:显示不可见字符,如制表符、换行符等23。
-e:等价于-vE选项,显示不可打印字符,如控制字符等23。
-t:等价于-vT选项,显示制表符23。


nl 查看文件的时候,显示行号,相当于 cat -b 
tac 逆向显示文件内容
rev 内容逆向显示,行内容也逆向显示
hexdump 以十六进制方式查看任意文件
hexdump 以十六进制方式查看任意文件,在检测文件系统分区的时候会用到


1.3.2 分页查看

more命令  可以实现分页查看文件,可以配合管道实现输出信息的分页

less命令 也可以实现分页查看文件或STDIN输出,less 命令是man命令使用的分页器
常用选项
-e    显示完成后自动退出      
-N    显示行号     
-s    压缩连续空行   
-S    不换行显示较长的内容

查看动作
:h    显示帮助           
/string   搜索关键字      
:!cmd       执行命令 
b        向上翻


1.3.3 头尾查看

head命令: 可以显示文件或标准输入的前面行,默认查看前10行

tail命令: 和head相反,查看文件或标准输入的倒数行,默认查看末尾10行
-n  指定行数
-f  跟踪显示文件fd新追加的内容,常用日志监控

生产中使用技巧:
head + tail  获取 指定范围的内容--行为单位
head -n14 filename | tail -n1  #查看第十四行


1.3.4 切割替换

cut 命令可以提取文本文件或STDIN数据的指定列
cat 的生产作用指定分隔符,获取列表内容。
常用选项
-c, --characters=列表      只选中指定的这些字符
-d, --delimiter=分界符     使用指定分界符代替制表符作为区域分界
-f, --fields=LIST         只选中指定的字节


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个字符开始截取后面所有字符   
cut -c-5 1.txt        从第5个字符开始截取前面所有字符


tr命令
实现 字符转换、替换、删除
用法:tr [选项]... SET1 [SET2]
从标准输入中替换、缩减和/或删除字符,并将结果写到标准输出。

用法1:把commands命令输出做为tr输入进行处理
commands | tr  'string1'  'string2'

用法2:把文件中的内容输入给tr进行处理
tr  'string1'  'string2' < filename

用法3:把文件中的内容输入给tr进行处理,需要使用到选项
tr options 'string1' < filename

用法4: 删除不匹配的所有内容,仅留下有用的信息
tr -dc [:alnum:] 


案例:
转换大小写
[root@rocky9 ~]# tr '[a-z]' '[A-Z]' < test1.txt  



生产技巧:
cut -d'分隔符' -f列  --打印内容
tr "原内容" "替换后内容"

案例:
[root@rocky9 ~]# ifconfig ens160 | head -n2 | tail -n1 | tr -s " " | cut -d " " -f 3
10.0.0.13    #提取IP地址


1.3.5 信息排序

sort命令,实现信息排序
常见选项:
-u :去除重复行
-r :降序排列,默认是升序
-n :以数字排序,默认是按字符排序
其他选项
-o : 将排序结果输出到文件中  类似 重定向符号>
-t :分隔符
-k :第N列
-b :忽略前导空格。
-R :随机排序,每次运行的结果均不同。



uniq命令 实现连续信息的去重动作
-c, --count    统计重复行次数
-d, --repeated   只显示重复行
-i, --ignore-case   忽略大小写

uniq -i uniq.txt   大小写不敏感去重
uniq -ic uniq.txt    大小写不敏感去重后计数       
uniq -d uniq.txt    仅显示重复的内容        
sort -n num.txt  | uniq     结合sort排序后去重



生产中 sort 和 uniq 往往在一起使用
使用样式:| uniq -c | sort -r


1.3.6 内容合并

paste命令
合并文件行内容输出到屏幕,不会改动源文件
-d, --delimiters=列表   #改用指定列表里的字符替代制表分隔符
-s, --serial  #不使用平行的行目输出模式,而是每个文件占用一行
--help   #显示此帮助信息并退出       
--version  显示版本信息并退出      

一般用于大型脚本场景:多个命令输出结果,进行合并处理。

内容合并
paste a.txt b.txt

自定义分隔符后合并内容
[root@rocky9 ~]# paste -d'@' b.txt a.txt
world@hello
888@
999@

将一个文件所有内容一行输出
[root@rocky9 ~]# paste -s b.txt
 world   
888     
999
 [root@rocky9 ~]# paste -d'@' -s b.txt
 world@888@999
xargs命令
作用:
xargs 可以将管道或标准输入(stdin)数据转换成命令行参数,也能够从文件的输出中读取数据。
xargs 一般是和管道一起使用。和find 命令合作也多。
-0:处理空字符而非空格作为参数分隔符。
- -a:从文件读取参数,而非标准输入。
- -d:指定分隔符,缺省为空白符(空格、换行等)。
- -E:设置“文件结束符”。在处理标准输入时,如果遇到“文件结束符”,则其后的所有输入都将被忽略。
- -i==-I:参数替换,用从标准输入读取的参数替换initial-arguments中的内容{};
          如果需要指定非{},则使用-I选项指定。
- -n:指定每个命令行参数的个数。
- -P:指定并行执行的最大进程数。
- -p:执行命令前提示用户确认。
- -r:忽略无法执行的命令。
- -s:限制命令及参数总字符数。
- -t:在执行命令之前先打印命令。
-x:确保xargs在命令行长度超出限制时停止执行。


从文件中读取内容
[root@rocky9 ~]# xargs -a num.txt
 9 8 6 8 4 7 2 1
 从文件中读取内容时,指定内容结束符号
[root@rocky9 ~]# xargs -a num.txt -E 4
 9 8 6 8
 从文件中读取内容时,询问用户是否显示,y显示,其他不显示
[root@rocky9 ~]# xargs -a num.txt -p
 echo 9 8 6 8 4 7 2 1 ?...y
 9 8 6 8 4 7 2 1
 从文件中读取内容时,指定每行显示几个内容
[root@rocky9 ~]# xargs -a num.txt -n4
 9 8 6 8
 4 7 2 1
 
 默认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
 
 -I的综合运用,转移文件并改名
 [root@rocky9 ~]# ls *.txt | xargs -n1 -I {} cp {} /tmp/{}-bak
 [root@rocky9 ~]# ls /tmp/*-bak
 /tmp/a.txt-bak  /tmp/num.txt-bak



2 三剑客

2.1 sed & grep

2.1.1 grep

grep 负责从数据源中检索对应的字符串,行过滤

生产使用技巧:
grep -nir 关键字 /路径 #用于快速检索,核心配置内容,修改配置
在脚本中:
grep -n xxx | cut -d":" -f1  #获取行号
或者交给sed进行内容替换。

常见选项:
-i: 不区分大小写
-n: 显示行号
-r: 逐层遍历目录查找
-v: 查找不包含指定内容的行,反向选择
-E:使用扩展正则匹配
^key:以关键字开头
key$:以关键字结尾
^$:匹配空行

一般选项:
-w: 按单词搜索
-o: 打印匹配关键字
-c: 统计匹配到的次数
-A: 显示匹配行及后面多少行 
-B: 显示匹配行及前面多少行
-C: 显示匹配行前后多少行
-l:只列出匹配的文件名
-L:列出不匹配的文件名
-e: 使用正则匹配
--color=auto :可以将找到的关键词部分加上颜色的显示

grep 高亮显示

grep 高亮显示
centos 和 Rocky 中已经为大家设置了,存放在/etc/profile.d/colorgrep.sh文件中;而
ubuntu将grep 的高亮显示放到了 ~/.bashrc 文件中。如若大家使用的系统中没有设置颜色输出,可以使

用以下方法来自行设置
临时设置:
# alias grep='grep --color=auto'            
永久设置:
1)全局(针对所有用户生效)
vim /etc/bashrc
alias grep='grep --color=auto'
source /etc/bashrc
//只针对当前终端和当前用户生效
2)局部(针对具体的某个用户)
vim ~/.bashrc
alias grep='grep --color=auto'
source ~/.bashrc

简单实践

常用命令选项必知必会  示例:
# 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行



2.1.2 sed基础

sed(Stream EDitor) 属于一种数据流式的行文件编辑工具。因为它编辑文件的时候,在内存中开辟一块额外的模式空间(pattern space),然后以行为单位读取文件内容到该空间中,接着sed命令处理该空 间中的内容,默认在当前终端界面打印内容,然后清空模式空间内容,再来读取第二行内容,依次循环下去。

基本格式    
sed [参数] '<匹配条件> [动作]' [文件名]
注意:
匹配条件和动作两侧有'
动作可以有多个,彼此间使用;隔开,比如 '2p;4p'


参数详解:
参数为空  表示sed的操作效果,实际上不对文件进行编辑,缓存区所有信息都显示   
-n   不输出模式空间内容到屏幕,即不自动打印所有内容       
-e   基于命令实现对文件的多点编辑操作        
-f   从指定文件中读取编辑文件的”匹配条件+动作”       
-r   支持使用扩展正则表达式       
-i.bak  复制文件原内容到备份文件,然后对原文件编辑   
-i    表示对文件进行编辑      


注意:
mac版本的bash中使用 -i参数,必须在后面单独加个东西: -i ''
-i -r 支持  -ri 支持
-ir  不支持
-ni  危险选项,会清空文件


匹配条件分为两种:数字行号或者关键字匹配
数字行号:
空   表示所有行             
n    表示第n行             
n,m    表示第n到m行内容       
~步进 1~2  表示奇数行 
2~2  表示偶数行
n,+m  表示第n到n+m行
$   表示末尾行

关键字匹配格式:
'/关键字/'
注意:
隔离符号 / 可以更换成 @、#、!等符号,
根据情况使用,如果关键字和隔离符号有冲突,就更换成其他的符号即可。

/关键字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的时候使用,不然的话不会有效果

简单实践:

默认打印信息
[root@rocky9 ~]# sed '2p' sed.txt  #除了打印第二行,还会显示所有信息 
nihao sed1 sed2 sed3
nihao sed4 sed5 sed6
nihao sed4 sed5 sed6   # 这一行才是操作的内容,其他的都是缓存区自动输出         
nihao sed7 sed8 sed9

打印第2行,不输出缓存区默认的其他信息
[root@rocky9 ~]# sed -n '2p' sed.txt
nihao sed4 sed5 sed6   #只显示指定的一行
打印第1,3行,不输出缓存区默认的其他信息
[root@rocky9 ~]# sed -n '1p;3p' sed.txt
打印包含sed4的行
[root@rocky9 ~]# sed -n '/sed4/p' sed.txt
打印奇数行
[root@rocky9 ~]# sed -n '1~2p' sed.txt 
打印偶数行
[root@rocky9 ~]# sed -n '0~2p' sed.txt
用-e实现多次文件编辑动作
[root@rocky9 ~]# sed -n -e '1p' -e '3p' sed.txt

sed命令可以借助外部文件里面的命令实现文件编辑
将文件操作命令输出到一个文件
[root@rocky9 ~]# echo -e "1p\n3p" > sed_script
[root@rocky9 ~]# sed -n -f sed_script sed.txt 

取反显示
显示除了第二行的内容,!代表非的意思
[root@rocky9 ~]# sed -n '2!p' sed.txt   

查看内容属于第几行
[root@rocky9 ~]# sed -n '/sed4/=' sed.txt

2.1.3 sed替换

sed的文本替换动作是使用频率最高的一种样式。它的基本表现样式如下:
命令格式:
sed -i [替换格式] [文件名]
源数据 | sed -i [替换格式]
注意:替换命令的写法
's###'  --->  's#原内容##' ---> 's#原内容#替换后内容#'
隔离符号 / 可以更换成 @、#、!等符号

表现样式:
样式一:替换指定匹配的内容,若行号不写代表所有行,列号不写表示第一个
sed -i '行号s#原内容#替换后内容#列号' [文件名]
echo "源数据" | sed -i '行号s#原内容#替换后内容#列号'
样式二:替换所有的内容,最后的g表示替换所有内容。
sed -i 's#原内容#替换后内容#g' [文件名]
echo "源数据" | sed -i '行号s#原内容#替换后内容#g'
样式三: 替换指定的内容
sed -i '行号s#原内容#&新增信息#列号' [文件名]- 这里的&符号代表源内容,实现的效果是 '原内容+新内容'

5-文本处理工具和正则表达式_vim_02

简单实践

实践1-替换每行首个匹配内容

格式:sed -i 's#原内容#替换后内容#' 文件名
替换首每行的第1个sed为SED,
 [root@rocky9 ~]# sed -i 's#sed#SED#' sed.txt  
[root@rocky9 ~]# cat sed.txt 
nihao SED1 sed2 sed3
nihao SED4 sed5 sed6
nihao SED7 sed8 sed9

实践2-替换全部匹配内容

格式:sed -i 's#原内容#替换后内容#g' 文件名 :替换全部匹配内容
替换全部sed为des
[root@rocky9 ~]# sed -i 's#sed#SED#g' sed.txt 
[root@rocky9 ~]# cat sed.txt 
nihao SED1 SED2 SED3
nihao SED4 SED5 SED6
nihao SED7 SED8 SED9
 
关于全部替换还有另外一种命令叫直接转换 y
[root@rocky9 ~]# sed 'y/SED/sed/' sed.txt
nihao sed1 sed2 sed3
nihao sed4 sed5 sed6
nihao sed7 sed8 sed9

实践3-指定行号替换首个匹配内容

格式:sed -i '行号s#原内容#替换后内容#' 文件名
替换第2行的首个SED为sed
[root@rocky9 ~]# sed -i '2s#SED#sed#' sed.txt  #行号2,列号没写默认第一列
[root@rocky9 ~]# cat sed.txt 
nihao SED1 SED2 SED3
nihao sed4 SED5 SED6
nihao SED7 SED8 SED9

实践4-首行指定列号替换匹配内容

格式:sed -i 's#原内容#替换后内容#列号' 文件名
替换每行的第2个SED为sed
[root@rocky9 ~]# sed -i 's#SED#sed#2' sed.txt   #列号2,行号没写默认第一行
[root@rocky9 ~]# cat sed.txt 
nihao SED1 sed2 SED3
 nihao sed4 SED5 sed6
 nihao SED7 sed8 SED9

实践5-指定行号列号匹配内容

格式:sed -i '行号s#原内容#替换后内容#列号' 文件名
替换第3行的第2个SED为sed
[root@rocky9 ~]# sed -i '3s#SED#sed#2' sed.txt 
[root@rocky9 ~]# cat sed.txt 
nihao SED sed2 SED3
nihao sed4 SED5 sed6
nihao SED7 sed8 sed9

实践6-综合实践

借助正则的分组功能实现ip地址获取,-r 支持使用扩展正则表达式
[root@rocky9 ~]# ifconfig eth0 | sed -n '2p' | sed -r 's#.*inet (.*) net.*#\1#'
10.0.0.12
[root@rocky9 ~]# ifconfig eth0 | sed -n '2p' | sed -r 's#.*inet ##' | sed -r 's# net.*##' 
10.0.0.12

==============================================================
命令拆解:(下面换了个服务器所以IP不一样)
打印网卡信息第二行
[root@iv-yd00fvur5scva4f5dfgk ~]# ifconfig eth0 | sed -n '2p'
        inet 192.168.0.2  netmask 255.255.0.0  broadcast 192.168.255.255
把所有以.inet开头和后面一个空格 的内容,替换为(替换内容没写就是删除原内容)。
[root@iv-yd00fvur5scva4f5dfgk ~]# ifconfig eth0 | sed -n '2p' | sed -r 's#.*inet ##'
192.168.0.2  netmask 255.255.0.0  broadcast 192.168.255.255
再把 空格和net后面所有内容替换(替换内容没写就是删除原内容),这样就只剩下IP了。
[root@iv-yd00fvur5scva4f5dfgk ~]# ifconfig eth0 | sed -n '2p' | sed -r 's#.*inet ##' | sed -r 's# net.*##'
192.168.0.2
==============================================================

借助正则的分组功能实现信息的精确获取
[root@rocky9 ~]# echo '/etc/sysconfig/network' | sed -r 's#(.*\/)([^/]+\/?$)#\2#'
network
[root@rocky9 ~]# echo '/etc/sysconfig/network' | sed -r 's#(.*\/)([^/]+\/?$)#\1#'
/etc/sysconfig/

5-文本处理工具和正则表达式_sed_03


2.1.4 增加操作

追加实践&&基本语法

作用:在指定行号的下一行增加内容
格式:
sed -i '行号a\增加的内容' 文件名
注意:
如果增加多行,可以在行号位置写个范围值,彼此间使用逗号隔开,例如
sed -i '1,3a\增加内容' 文件名

5-文本处理工具和正则表达式_sed_04

实践1-基于行号实践

指定行号增加内容
[root@rocky9 ~]# sed -i '2a\zengjia-2' sed.txt 
[root@rocky9 ~]# cat sed.txt 
nihao SED sed2 SED3
nihao sed4 SED5 sed6   
zengjia-2     #在原来第二行的下面增加
nihao SED7 sed8 sed9

指定1~3每行都增加内容
[root@rocky9 ~]# sed -i '1,3a\tongshi-2' sed.txt 
[root@rocky9 ~]# cat sed.txt 
nihao SED sed2 SED3
tongshi-2
nihao sed4 SED5 sed6
tongshi-2
zengjia-2
tongshi-2
nihao SED7 sed8 sed9

插入实践&&基本语法

作用:在指定行号的当行增加内容
格式:
sed -i '行号i\增加的内容' 文件名
注意:
如果增加多行,可以在行号位置写个范围值,彼此间使用逗号隔开,例如
sed -i '1,3i\增加内容' 文件名

实践1-基于行号实践

指定行号增加内容
[root@rocky9 ~]# sed -i '1i\insert-1' sed.txt 
[root@rocky9 ~]# cat sed.txt 
insert-1
nihao SED sed2 SED3
tongshi-2
nihao sed4 SED5 sed6
tongshi-2
zengjia-2
tongshi-2
nihao SED7 sed8 sed9

指定1~3每行都增加内容
[root@rocky9 ~]# sed -i '1,3i\insert-2' sed.txt 
[root@rocky9 ~]# cat sed.txt
insert-2
insert-1
insert-2
nihao SED sed2 SED3
insert-2
tongshi-2
nihao sed4 SED5 sed6
tongshi-2
zengjia-2
tongshi-2
nihao SED7 sed8 sed9


2.1.5 删除替换

删除实践&&基本语法

作用:指定行号删除
格式:
sed -i '行号d' 文件名
注意:
如果删除多行,可以在行号位置多写几个行号,彼此间使用逗号隔开,例如
sed -i '1,3d' 文件名

实践1-基于行号实践

删除第4行内容
[root@rocky9 ~]# sed -i '4d' sed.txt 
[root@rocky9 ~]# cat sed.txt 
insert-2
insert-1
insert-2
insert-2
tongshi-2
nihao sed4 SED5 sed6
tongshi-2
zengjia-2
tongshi-2
nihao SED7 sed8 sed9

删除多行(1-6行)内容
[root@rocky9 ~]# sed -i '1,6d' sed.txt
[root@rocky9 ~]# cat sed.txt
tongshi-2
zengjia-2
tongshi-2
nihao SED7 sed8 sed9

替换实践&&基本语法

作用:指定行号进行整行替换
格式:
sed -i '行号c\内容' 文件名
注意:
如果替换多行,可以在行号位置多写几个行号,彼此间使用逗号隔开,例如
sed -i '1,3c\内容' 文件名

实践1-基于行号实践

替换第3行内容
[root@rocky9 ~]# sed -i '3c\tihuan-1' sed.txt
[root@rocky9 ~]# cat sed.txt
tongshi-2
zengjia-2
tihuan-1
nihao SED7 sed8 sed9
 
指定1~3行都替换成一行内容
[root@rocky9 ~]# sed -i '1,3c\tihuan-3' sed.txt
[root@rocky9 ~]# cat sed.txt
tihuan-3
nihao SED7 sed8 sed9

2.1.6 加载保存

加载实践&&基本语法

作用:加载文件内容到指定行号的位置
格式:
sed -i '行号r 文件名1' 文件名
注意:
如果在多行位置加载,可以在行号位置多写几个行号,彼此间使用逗号隔开,例如
sed -i '1,3r 文件名1' 文件名

5-文本处理工具和正则表达式_vim_05

实践1-基于行号实践

加载第3行内容
[root@rocky9 ~]# sed -i '2r sed.txt' sed.txt
[root@rocky9 ~]# cat sed.txt
tihuan-3
nihao SED7 sed8 sed9
tihuan-3
nihao SED7 sed8 sed9
注意;
由于缓存区中文件内容的顺序变化,导致加载的内容顺序不一致
把文件sed_script里的内容 加载到sed.txt文件的第2到4行下面:
[root@rocky9 ~]# sed -i '2,4r sed_script' sed.txt
[root@rocky9 ~]# cat sed_script
1p
3p
[root@rocky9 ~]# cat sed.txt 
tihuan-3
nihao SED7 sed8 sed9
1p
3p
tihuan-3
1p
3p
nihao SED7 sed8 sed9
1p
3p

保存实践&&基本语法

5-文本处理工具和正则表达式_vim_06

实践1-基于行号实践

保存第3行内容
[root@rocky9 ~]# sed -i '2w sed_test' sed.txt
[root@rocky9 ~]# cat sed_test
nihao SED7 sed8 sed9
指定2~4行内容保存到一个文件中
[root@rocky9 ~]# sed -i '1,4w sed_test' sed.txt
[root@rocky9 ~]# cat sed_test
tihuan-3
nihao SED7 sed8 sed9
1p
3p


2.1.7 匹配进阶

5-文本处理工具和正则表达式_sed_07

简单实践

实践1-内容的简单匹配显示

查看匹配的内容
注意:p是sed 的一个打印命令(print)
[root@rocky9 ~]# sed -n '/send/p' nginx.conf 
 sendfile    on;
匹配内容间的多行信息
[root@rocky9 ~]# sed -n '/send/,/server/p' nginx.conf
 sendfile        
on;
 keepalive_timeout  65;
 server {
查看匹配内容到第6行的内容
[root@rocky9 ~]# sed -n '/send/,6p' nginx.conf
 sendfile        
on;
 keepalive_timeout  65;
查看第1行到匹配行的内容
[root@rocky9 ~]# sed -n '1,/send/p' nginx.conf
 #user  nobody;
 worker_processes  1;
 http {
 sendfile        
on;
查看匹配内容和下面三行的内容
[root@rocky9 ~]# sed -n '/send/,+3p' nginx.conf
 sendfile        
on;
 keepalive_timeout  65;
 server {
 
=====================================================================
通过 !p 去除空行匹配
!: 这个符号在 sed 中用作逻辑非(NOT)操作符。它反转后面命令的默认行为。
/^$/: 这是一个正则表达式,匹配空行;
^ 表示行的开始,$ 表示行的结束,所以 ^$ 匹配那些开始和结束都紧邻在一起的行,即没有任何字符的行,也就是空行
=====================================================================
[root@rocky9 ~]# sed -n '/^$/!p' nginx.conf     #打印非空的行
#user  nobody;
 worker_processes  1;
 http {
 sendfile        
on;
 keepalive_timeout  65;
 server {
 listen       
8000;
 server_name  localhost;
 location / {
 root   html;
 index  index.html index.htm;
 }
 }
 }
 
=====================================================================
借助分组功能,实现多信息的剔除
正则式拆解:
^:这个符号表示行的开始
然后(#|$)是一个分组,使用 | 作为逻辑或(OR)操作符。它表示匹配以下两个选项之一:
#:表示行以 # 开头。
$:这个符号表示行的结束。当 $ 与 ^ 一起使用时,并且它们之间没有其他字符,那么这个表达式就匹配一个空行。
所以:
^(#|$)表示匹配所有以#开头的行 和 所有空行。
/^(#|$)/!p  表示打印 除了 所有以#开头的行 和 所有空行 的内容。
=====================================================================
打印除了 以#开头和空行 的内容
[root@rocky9 ~]# sed -rn '/^(#|$)/!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;
 }
 }
 }


实践2-分组信息显示

获取制定文件所在的路径信息
[root@rocky9 ~]# echo "/etc/sysconfig/network" |sed -r 's#(^/.*/)([^/]+/?)#\1#'
 /etc/sysconfig/
 
=========================================================================
命令拆解:正则部分's#(^/.*/)([^/]+/?)#\1#'
s#()()#\1#: 是一种格式
2个括号分别代表2个捕获组,\1 表示第一个捕获组的内容;\2表示第二个捕获组的内容。
举例:
s#(1)(2)#\1# :取1个捕获组
s#(1)(2)#\2# :取第二个捕获组
取123捕获组以-号分隔
echo "foo123bar" | sed -r 's#(foo)([0-9]+)(bar)#\1-\2-\3#'
 
 第一个捕获组 (^/.*/):匹配以/开头到最后一个/之中所内容,包括2个/本身。
 ^:表示行的开始。
 ^/: 表示以匹配/为开头
 .*:表示配任意长度的字符串(除了换行符)
 /:再次出现的字面字符 /,表示另一个路径分隔符。
 由于后面的\1表示第一个捕获组的内容
 所以:^/.*/ 实际上会匹配以 / 开头的任意字符串,直到最后一个 / 之前的部分。
 对于这段内容:/etc/sysconfig/network
 结果就是:/etc/sysconfig/
 
 第二个捕获组 ([^/]+/?):匹配所有非/字符
 方括号 [] 表示字符类
 ^ 在字符类内部表示否定(即不匹配方括号内的字符)
 因此,[^/]+  表示匹配一个或多个非 / 字符。
 /?:问号 ? 表示前面的元素(在这里是 /)可以出现零次或一次

=========================================================================
 
 
 
获取制定文件名称
[root@rocky9 ~]# echo "/etc/sysconfig/network" |sed -r 's#(^/.*/)([^/]+/?)#\2#'
network
=========================================================================
s#(^/.*/)([^/]+/?)#\2#   取第二个捕获组
[^/]+/? :
对于/etc/sysconfig/network 
第二捕获组这部分可以简化:([^/]*) 匹配第一捕获组以外所有非 / 内容
就是除了/etc/sysconfig/以外,network 这段内容。
echo "/etc/sysconfig/network" | sed -r 's#(^/.*/)([^/]+/?)#\1#'
echo "/etc/sysconfig/network" | sed -r 's#(^.*/)([^/]*)#\1#' 
这2个效果一样,第二个更精简。当然要更具具体的内容而定。
=========================================================================


获取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: 表示替换为第一个捕获组的内容。

5-文本处理工具和正则表达式_sed_03


2.1.8 文件处理

多点操作

我们可以借助 '动作1;动作2' 或者 -e '动作1' -e '动作2' 的方式实现多操作的并行实施

实践1-内容的过滤编辑

不显示所有空行和注释信息
[root@rocky9 ~]# sed '/^#/d;/^$/d' nginx.conf
[root@rocky9 ~]# sed -rn '/^(#|$)/!p' nginx.conf  #前面用的这个命令也行:打印除了以#开头和空行的内容
 
先剔除空行,然后不显示所有包含注释的信息
[root@rocky9 ~]# sed -rn '/^$/d;/^[[:space:]]*#/!p' nginx.conf

实践2-借助于 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;


增改实践

实践1-借助于&符号实现内容的扩充式更改编辑

查看原内容
[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

实践2-借助于s实现内容的替换式更改编辑

显示/etc/fstab文件中非#开头的内容,就是没被注释的内容
[root@master-192-168-0-2 ~]# sed -n '/^#/!p' /etc/fstab
UUID=24fd1325-bbf3-4814-b7e9-041deba41f10  /        ext4  defaults,errors=remount-ro  0 1
UUID=F315-B9A3  /boot/efi       vfat    umask=0077      0       1
[root@master-192-168-0-2 ~]#

把这些没被注释的内容注释掉,就是开头加上#号
[root@master-192-168-0-2 ~]# sed -rn '/^#/!s@^@#@p' /etc/fstab
#UUID=24fd1325-bbf3-4814-b7e9-041deba41f10  /        ext4  defaults,errors=remount-ro  0        1
#UUID=F315-B9A3  /boot/efi       vfat    umask=0077      0      1
[root@master-192-168-0-2 ~]#

实践3-借助于 i|a 对文件进行 插入|追加 式更改编辑

准备一个nginx.conf文件

基于内容匹配相关信息并打印
打印nginx.conf文件中所有包含listen的行:
[root@master-192-168-0-2 ~]# cat nginx.conf
http {

    server {
        listen       80;  #原本的listen
        listen       [::]:80;
        server_name  _;
        root         /usr/share/nginx/html;

        location = /50x.html {
        }
    }

基于内容匹配追加1行内容,a\ 表示在匹配行下追加,\t 表示空格
在每个有listen字段的行,增加:
        listen          80;    #增加的
[root@master-192-168-0-2 ~]# sed '/listen/a\\tlisten\t\t80;' nginx.conf
http {

    server {
        listen       80;  #原本的listen
        listen          80;    #增加的
        listen       [::]:80;
        listen          80;    #增加的
        server_name  _;
        root         /usr/share/nginx/html;

        location = /50x.html {
        }
    }

基于内容匹配插入2行内容 -- 借助于\n的换行功能,将1行变成两行
i\ 表示在匹配行上插入,\t 表示空格
在原本有listen字段的行之上,插入2行内容:
        listen          80;
        listen          8080;
[root@master-192-168-0-2 ~]# sed '/listen/i\\tlisten\t\t80;\n\tlisten\t\t8080;' nginx.conf
http {

    server {
        listen          80;
        listen          8080;  
        listen       80;  #原本的listen
        listen          80;
        listen          8080;
        listen       [::]:80;  #原本的listen
        server_name  _;
        root         /usr/share/nginx/html;

        location = /50x.html {
        }
    }

实践4-借助于 环境变量和s|c 对文件进行 修改|替换 式更改编辑

查看nginx文件原本信息,默认port是80,server_name 是空的
[root@master-192-168-0-2 ~]# cat nginx.conf
http {

    server {
        listen       80;
        listen       [::]:80;
        server_name  _;
        root         /usr/share/nginx/html;

        location = /50x.html {
        }
    }


自定义一下port
[root@master-192-168-0-2 ~]# port=2531

使用多点修改,nginx文件里的port变成自定义的了:
port是8080,server_name master-192-168-0-2:2531
[root@master-192-168-0-2 ~]# sed -r -e "s/listen.*;/listen\t$port;/" -e '/server_name/c \\tserver_name '$(hostname):$port';' nginx.conf
http {

    server {
        listen  2531;
        listen  2531;
        server_name master-192-168-0-2:2531;
        root         /usr/share/nginx/html;

        location = /50x.html {
        }
    }

[root@master-192-168-0-2 ~]#

================================================================================
命令拆解:
-e "s/listen.*;/listen\t$port;/"
匹配 listen 到; 号的所在行,替换内容为:listen $port;(\t是空格)
-e '/server_name/c\\tserver_name '$(hostname):$port';' 
匹配server_name所在行,将这行内容 用 c\ 替换为
\tserver_name '$(hostname):$port'; (\t是空格)
就是server_name master-192-168-0-2:2531;

sed 替换格式:
sed -i '行号c\内容' 文件名

================================================================================

注意:
这里涉及到环境变量的解读,千万不要被单引号转义了




2.2 AWK基础

2.2.1 awk基础

5-文本处理工具和正则表达式_分隔符_09


5-文本处理工具和正则表达式_vim_10


5-文本处理工具和正则表达式_vim_11


5-文本处理工具和正则表达式_vim_12


5-文本处理工具和正则表达式_vim_13


5-文本处理工具和正则表达式_分隔符_14


2.2.2 基础语法

信息查看&&字段提取

5-文本处理工具和正则表达式_vim_15

准备工作

[root@rocky9 ~]# cat awk.txt
nihao awk1 awk2 awk3
nihao awk4 awk5 awk6
nihao awk7 awk8 awk9

实践1-打印列信息

打印第1列的内容
[root@rocky9 ~]# awk '{print $1}' awk.txt
 nihao
 nihao
 nihao
打印第3列内容
[root@rocky9 ~]# awk '{print $3}' awk.txt
 awk2
 awk5
 awk8
打印最后一列信息
[root@rocky9 ~]# awk '{print $NF}' awk.txt
 awk3
 awk6
 awk9
打印所有内容
[root@rocky9 ~]# awk '{print $0}' awk.txt
 nihao awk1 awk2 awk3
 nihao awk4 awk5 awk6
 nihao awk7 awk8 awk9
 
$0虽然是表示整行,但是默认会每一行执行这个,若要限制行数 用NR参数
awk 'NR==1 {print $0}' awk.txt

实践2-打印多列信息

打印第3,8列内容
[root@rocky9 ~]# awk '{print $1,$3}' awk.txt
 nihao awk2
 nihao awk5
 nihao awk8
打印信息时候,合并信息
[root@rocky9 ~]# awk '{print $1$3}' awk.txt
 nihaoawk2
 nihaoawk5
 nihaoawk8
使用\t实现内容的分割,需要用""扩住
[root@rocky9 ~]# awk '{print $1"\t"$3}' awk.txt
 nihao   awk2
 nihao   awk5
 nihao   awk8
 
打印列外普通信息
[root@rocky9 ~]# awk '{print "hello awk"}' awk.txt
 hello awk
 hello awk
 hello awk
注意:
如果没有$n的话,表示 print动作执行的次数与文件行数一致
打印fstab的关键信息
[root@rocky9 ~]# grep "^UUID" /etc/fstab |awk {'print $1,$3'}
 UUID=5583bd7c-cc9f-4e19-b453-c224102f3ed5 xfs
 UUID=cbd246cd-1df8-4fe7-9040-823cd0978837 xfs

实践3-行号信息输出

打印每列的行号信息
[root@rocky9 ~]# awk '{print NR,$0}' awk.txt
 1 nihao awk1 awk2 awk3
 2 nihao awk4 awk5 awk6
 3 nihao awk7 awk8 awk9
 
按照行号打印对应列的内容,$NR 是个变量,根据文件NR行号来
[root@rocky9 ~]# awk '{print NR, $NR}' awk.txt
 1 nihao    NR=1 就打印这一行第一列 nihao
 2 awk4     NR=2 就打印这一行第一列 awk4
 3 awk8     NR=3 就打印这一行第一列 awk8

实践4-打印特定行内容

制定行号打印信息
[root@rocky9 ~]# awk  'NR==1 {print NR,$1,$3}' awk.txt
 1 nihao awk2
 [root@rocky9 ~]# awk  'NR==2 {print NR,$1,$3}' awk.txt
 2 nihao awk5


定制查看

简介

5-文本处理工具和正则表达式_vim_16

实践1-简单演示

准备文件内容

[root@rocky9 ~]# head -n1 /etc/passwd > passwd.txt
 [root@rocky9 ~]# cat passwd.txt
 root:x:0:0:root:/root:/bin/bash
使用普通awk命令展示
[root@rocky9 ~]# awk '{print $1}' passwd.txt
root:x:0:0:root:/root:/bin/bash
[root@rocky9 ~]# awk '{print $2}' passwd.txt
[root@rocky9 ~]# awk '{print $0}' passwd.txt
root:x:0:0:root:/root:/bin/bash
结果显示:
文件中只有一列,无法被awk默认分离

实践2-定制分隔符

设定分隔符实现信息的分隔效果,-F ':' 以:号为分隔符
[root@rocky9 ~]# awk -F ':' '{print $0}' passwd.txt
root:x:0:0:root:/root:/bin/bash
[root@rocky9 ~]# awk -F ':' '{print $1}' passwd.txt
root
[root@rocky9 ~]# awk -F ':' '{print $1,$2}' passwd.txt
root x
[root@rocky9 ~]# awk -F ':' '{print $1,$7}' passwd.txt
root /bin/bash

基于-v方式设定输入分隔符的环境变量FS
[root@rocky9 ~]# awk -v FS=":" '{print $1FS$7}' passwd.txt
root:/bin/bash
 
虽然-v FS 和 -F 都可以设定入口数据的列分隔符,如果混用的话,-F的优先级高一点
[root@rocky9 ~]# awk -v FS=":" -F":" '{print $1FS$7}' passwd.txt
root:/bin/bash
[root@rocky9 ~]# awk -F":" -v FS=":"  '{print $1FS$7}' passwd.txt
root:/bin/bash

实践3-统计案例

获取网址域名信息
[root@rocky9 ~]# cat domain.txt
 http://www.example.org/index.html
 http://www.example.org/1.html
 http://api.example.org/index.html
 http://upload.example.org/index.html
 http://img.example.org/3.html
 http://search.example.org/2.html
对相关信息进行统计
===================================================================
【-F [/]+】==【F'/+'】 定义一个或多个连续的斜杠为分隔符,就是无视连续//,当作一个/
{print $2}:打印第二段字段
{print $(NF-1)} :打印倒数第二个字段
uniq -c :去重显示每行,并且记录重复的行出现的次数
===================================================================
[root@rocky9 ~]# awk -F[/]+ '{print $2}' domain.txt  | uniq -c
 2 www.sswang.org
 1 api.sswang.org
 1 upload.sswang.org
 1 img.sswang.org
 1 search.sswang.org
 [root@rocky9 ~]# awk -F[/]+ '{print $(NF-1)}' domain.txt  | uniq -c 
 2 www.sswang.org
 1 api.sswang.org
 1 upload.sswang.org
 1 img.sswang.org
 1 search.sswang.org


2.2.3 显示语法

5-文本处理工具和正则表达式_sed_17


简单实践

实践1-列输出分隔符实践

在 awk 命令中,FS、RS 和 ORS 是三个重要的变量,它们分别用于:
FS 控制输入字段分隔符、
RS 控制输入记录分隔符
ORS 控制输出记录分隔符
借助于-v方式为命令行输出相关信息
[root@rocky9 ~]# awk -F ':' -v OFS="~~~" '{print $1,$7}' passwd.txt
 root~~~/bin/bash
借助于BEGIN语句设定环境变量
[root@rocky9 ~]# awk -F":" 'BEGIN{OFS="~"} {print NR,$1,$7}' passwd.txt
 1~root~/bin/bash
在BEGIN内部同时实现多个环境变量
[root@rocky9 ~]# awk 'BEGIN{FS=":";OFS="-"}NR==1{print $1,$3,$NF}' passwd.txt
root-0-/bin/bash

实践2-行输入输出分隔符实践

定制输入分隔符
[root@server12 ~]# seq 7 | awk 'BEGIN{RS=""}{print $1,$2,$3,$4,$5,$6,$7}'
 1 2 3 4 5 6 7
借助于-v方式为行分隔符输出相关信息
[root@rocky9 ~]# awk -F ':' -v ORS="|" '{print $NR,$0}' awk.txt
nihao awk1 awk2 awk3 nihao awk1 awk2 awk3| nihao awk4 awk5 awk6| nihao awk7 awk8 
awk9|

借助于BEGIN语句设定环境变量
[root@rocky9 ~]# awk -F":" 'BEGIN{ORS="|"} {print NR,$0}' awk.txt
 nihao awk1 awk2 awk3 nihao awk1 awk2 awk3|2 nihao awk4 awk5 awk6|3 nihao awk7 
awk8 awk9|[root@rocky9 ~]#

实践3-printf格式化输出实践

使用print的格式信息
[root@rocky9 ~]# awk '{printf "%s\n",$1}' awk.txt
nihao
nihao
nihao
[root@rocky9 ~]# awk '{printf "%s",$1}' awk.txt; echo
nihaonihaonihao
 
多信息格式化嵌套
[root@rocky9 ~]# awk '{printf "%d--%s--%s\n", NR,$1,$NR}' awk.txt
1--nihao--nihao
2--nihao--awk4
3--nihao--awk8
 
数字的格式化输出     
[root@rocky9 ~]# awk '{printf "%4.2f--%s\n", NR,$1}' awk.txt
1.00--nihao
2.00--nihao
3.00--nihao

字符的格式化输出
[root@rocky9 ~]# awk '{printf "%-8s%s\n", NR,$1}' awk.txt
1   nihao    
2   nihao
3   nihao