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
效果展示:
============================================================================
=============================================================================
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#原内容#&新增信息#列号' [文件名]- 这里的&符号代表源内容,实现的效果是 '原内容+新内容'
简单实践
实践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/
2.1.4 增加操作
追加实践&&基本语法
作用:在指定行号的下一行增加内容
格式:
sed -i '行号a\增加的内容' 文件名
注意:
如果增加多行,可以在行号位置写个范围值,彼此间使用逗号隔开,例如
sed -i '1,3a\增加内容' 文件名
实践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' 文件名
实践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
保存实践&&基本语法
实践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 匹配进阶
简单实践
实践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: 表示替换为第一个捕获组的内容。
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基础
2.2.2 基础语法
信息查看&&字段提取
准备工作
[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
定制查看
简介
实践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 显示语法
简单实践
实践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