grep 、awk 、sed 号称是shell编程的三剑客
1、cut --提取,从命令结果中提取对应的内容
准备数据 1.txt
111:aaa:bbb:ccc
222:ddd:eee:fff
333:ggg:hhh
444:iii
cut 后面的 -c 的意思是按照字符选取内容
参数 | 英文 | 含义 |
-d '分隔符' | delimiter | 指定分隔符 |
-f n1,n2 | fields | 分割以后显示第几段内容, 使用 , 分割 |
参数 | 英文 | 含义 |
-c | characters | 按字符选取内容 |
范围控制
范围 | 含义 |
n | 只显示第n项 |
n- | 显示 从第n项 一直到行尾 |
n-m | 显示 从第n项 到 第m项(包括m) |
1、提取1.txt中前两行的第五个字符
head -2 1.txt // 查看文件的前两行
head -2 1.txt | cut -c 5
cut 本身也可以直接提取内容
cut -c 5 1.txt
2、截取1.txt文件中前两行以:进行分割的1,2,3段内容
head -2 1.txt | cut -d ':' -f 1,2,3
head -2 1.txt | cut -d ':' -f 1-3
将处理好的数据放入一个文件中:
head -2 1.txt | cut -d ":" -f 1,2,3 >> 111.txt
head -2 1.txt | cut -d ":" -f 2-
2、sort 排序
准备数据:2.txt
banana
apple
pear
orange
pear
对字符串进行排序,去重
参数 | 英文 | 含义 |
-u | unique | 去掉重复的 |
将 1.txt 中 第二列数据,倒序排列
[root@bigdata01 datas]# cut -d ":" -f 2 1.txt | sort -r
iii
ggg
ddd
aaa
数值类型操作
对数值类型进行的操作
参数 | 英文 | 含义 |
-n | numeric-sort | 按照数值大小排序 |
-r | reverse | 使次序颠倒 |
准备数据:3.txt
1
3
5
7
11
2
4
6
10
8
9
对成绩进行排序
参数 | 英文 | 含义 |
-t | field-separator | 指定字段分隔符 |
-k | key | 根据哪一列排序 |
造数据: 4.txt
zhangsan 68 99 26
lisi 98 66 96
wangwu 38 33 86
zhaoliu 78 44 36
maqi 88 22 66
zhouba 98 44 46
需求:根据第二个成绩进行倒序排序
结合cut 的做法:
cut -d ' ' -f 3 4.txt | sort -r -n
cat 4.txt | sort -t ' ' -k 3
sort -t ' ' -k 3 4.txt
3、wc (wordcount)--单词统计
wc 跟上文件名 显示文件的字节数,单词数,文件的行数
造数据:5.txt
111
222 bbb
333 aaa bbb
444 aaa bbb ccc
555 aaa bbb ccc ddd
666 aaa bbb ccc ddd eee
如果只想显示某一些数据:
参数 | 英文 | 含义 |
-c | bytes | 字节数 |
-w | words | 单词数 |
-l | lines | 行数 |
wc -l 5.txt
wc -l 1.txt 2.txt 3.txt 4.txt 5.txt
wc -l *.txt
我想看一下某个文件夹下有多少个文件
ls /etc | wc -w
ll /etc | wc -l
[root@bigdata01 scripts]# num=$[`ll | wc -l`-1]
[root@bigdata01 scripts]# echo $num
28
[root@bigdata01 scripts]# echo $[`ll | wc -l`-1]
28
4、awk(重点)
awk 可以实现模糊查询,按需截取字符串,进行判断以及简单的运算
1)查询 搜索名字中含有zhang 和li 的学生成绩
命令 | 含义 |
awk '/搜索字符/' score.txt | 模糊查询 |
模糊查询 '张三' ‘张三三'
cat 4.txt | awk '/zhang|li/'
awk '/zhang|li/' 4.txt
[root@bigdata01 scripts]# grep 'zhang' 4.txt
zhangsan 68 99 26
[root@bigdata01 scripts]# grep 'li' 4.txt
lisi 98 66 96
zhaoliu 78 44 36
2、指定分隔符,按照下标显示内容
命令 | 含义 |
awk -F ',' '{print $1,$2, $3}' 文件 | 操作1.txt文件, 根据 逗号 分割, 打印 第一段 第二段 第三段 内容 |
选项
选项 | 英文 | 含义 |
-F ',' | field-separator | 使用 指定字符 分割 |
$ + 数字 | 获取第几段内容 | |
$0 | 获取 当前行 内容 | |
NF | field | 表示当前行共有多少个字段 |
$NF | 代表 最后一个字段 | |
$(NF-1) | 代表 倒数第二个字段 | |
NR | 代表 处理的是第几行 |
打印4.txt 中每个学生的姓名以及前两门的成绩
cat 4.txt | awk -F ' ' '{print $1,$2,$3}'
跟这个效果一样:
cut -d ' ' -f 1,2,3 4.txt
命令 | 含义 |
awk -F ' ' '{OFS="==="}{print 2, $3}' 1.txt | 操作1.txt文件, 将打印出来的内容添加分隔符 |
选项 | 英文 | 含义 |
OFS="字符" | output field separator | 向外输出时的段分割字符串 |
awk中使用函数
命令 | 含义 |
awk -F ',' '{print toupper($2)}' 1.txt | 操作1.txt文件, 将某一列的数据变为大写 |
常用函数如下:
函数名 | 含义 | 作用 |
toupper() | upper | 字符 转成 大写 |
tolower() | lower | 字符 转成小写 |
length() | length | 返回 字符长度 |
实战:
cat 4.txt | awk -F ' ' '{print toupper($1)}'
awk -F ' ' '{if($2>=60) print "及格",$1,$2;else print "不及格",$1,$2}' 4.txt
awk中可以进行begin,end语句
命令 | 含义 |
awk 'BEGIN{初始化操作}{每行都执行} END{结束时操作}' 文件名 | BEGIN{ 这里面放的是执行前的语句 }{这里面放的是处理每一行时要执行的语句}END {这里面放的是处理完所有的行后要执行的语句 } |
//求最后一列成绩的总分
cat 4.txt | awk -F ' ' 'BEGIN{print "开始计算成绩总和"}{total=total+$4}END{print total}'
它是由三部分组成的
BEGIN{} 这一部分只执行一次
END{} 该代码块中的语句也只执行一次
中间{} 每读取一行数据,就执行一次
BEGIN 和 END 可以选择性的使用
// 获取记录条数:
cat 4.txt | awk -F ' ' 'BEGIN{print "开始计算成绩总和"}{total=total+$4}END{print total,NR}'
[root@bigdata01 scripts]# awk -F ' ' 'BEGIN{print "开始计算成绩:"}{total=total+$4}END{print "总成绩 是:"total",总条数是:"NR}' 4.txt
开始计算成绩:
总成绩是:356,总条数是:6
// 获取平均分
cat 4.txt | awk -F ' ' 'BEGIN{print "开始计算成绩总和"}{total=total+$4}END{print total,NR,(total/NR)}'
awk -F ' ' 'BEGIN{print "开始计算最后一个学科的总成绩"}{total=total+$4;print NR}END{print total/NR}' 4.txt
开始计算最后一个学科的总成绩
1
2
3
4
5
6
59.3333
[root@bigdata01 datas]# awk -F ' ' 'BEGIN{print "开始计算最后一个学科的总成绩"}{total=total+$4;print $0,NF,$NF}END{print total/NR}' 4.txt
开始计算最后一个学科的总成绩
zhangsan 68 99 26 4 26
lisi 98 66 96 4 96
wangwu 38 33 86 4 86
zhaoliu 78 44 36 4 36
maqi 88 22 66 4 66
zhouba 98 44 46 4 46
59.3333
$0 表示当前行的内容
NF 表示当前行有多少个字段
$NF 表示当前行的最后一个字段
[root@bigdata01 scripts]# awk -F ' ' '{print $0,NF,$NF}' 4.txt
zhangsan 68 99 26 4 26
lisi 98 66 96 4 96
wangwu 38 33 86 4 86
zhaoliu 78 44 36 4 36
maqi 88 22 66 4 66
zhouba 98 44 46 4 46
5、sed操作 --实现过滤和替换
1、可以进行查询操作
命令 | 含义 |
sed 可选项 目标文件 | 对目标文件 进行 过滤查询 或 替换 |
可选参数
可选项 | 英文 | 含义 |
p | 打印 | |
$ | 代表 最后一行 | |
-n | 仅显示处理后的结果 | |
-e | expression | 根据表达式 进行处理 |
2、搞一些数据 6.txt
aaa java root
bbb hello
ccc rt
ddd root nologin
eee rtt
fff ROOT nologin
ggg rttt
3、列出6.txt中的3~5行的数据
cat 6.txt | sed -n -e '3,5p'
假如没有学过sed可以这么干:
head -5 6.txt | tail -3
显示第一行到最后1行的数据
可选项 | 含义 |
= | 打印当前行号 |
打印第三行到第五航的数据,显示行号
一种写法,没有使用sed ,而是使用了cat -n
cat -n 6.txt|sed -n -e '3,5p'
另一种写法:
sed -n -e '3,5=' -e '3,5p' 6.txt
sed进行查找:
// 需求是查找每一行中包含login的数据
cat 6.txt | sed -n -e '/login/p'
cat 6.txt| grep login
[root@bigdata01 gaoji]# grep -n login 6.txt
4:ddd root nologin
6:fff ROOT nologin
[root@bigdata01 gaoji]# awk '/login/' 6.txt
ddd root nologin
fff ROOT nologin
[root@bigdata01 gaoji]# sed -n -e '/login/p' 6.txt
ddd root nologin
fff ROOT nologin
不区分大小写的查找,使用 I 参数 (大i)
Sed 中可以使用正则表达式
cat 6.txt|sed -n -r -e '/r+t/p'
-r 后面可以跟正则表达式
r+ 表示 r 可以出现一次到多次 r后面必须跟上t
思考: 在这个里面如何写一个正则表达式,表示以r开头,以t结尾
a* a出现0次到多次
a+ a出现1次到多次
Sed 进行删除操作:
先学习一个新命令 nl 可以查看文件,该文件自动添加行号
nl 6.txt
选项使用d 进行删除
显示除了3到5行的所有数据:
nl 6.txt | sed -e '3,5d'
nl 6.txt | sed -e '3,$d' // 只显示前两行数据了
[root@bigdata01 datas]# cat 6.txt | sed -e '3,$d' | cut -d ' ' -f 2
java
hello
还可以使用sed修改内容
参数 | 英文 | 含义 |
i | insert | 目标前面 插入内容 |
a | append | 目标后面 追加内容 |
1、在6.txt的第一行前面插入 xxxxxxx,并显示行号
nl 6.txt | sed -e '1i xxxxxxxx'
2、在6.txt的第二行后面插入 SSSSSSS,并显示行号
nl 6.txt | sed -e '2a SSSSSSSS'
sed还可以进行数据的替换
s/oldString/newString/ | replace | 替换 |
把6.txt中的nologin替换成为huawei,并显示行号
cat 6.txt | sed -e 's/nologin/huawei/' // 按照字符串进行替换
cat 6.txt | sed -e '3c laoyan' // 按照行进行替换
上的替换都是没有修改原来的数据的,sed也可以直接对原数据进行直接更改。
直接更改数据,首先数据进行备份
cp 6.txt 7.txt
sed -i -e 's/nologin/huawei/' 7.txt
sed -i -e '2c laoyanlaoyan' 7.txt
sed -i -e '1,2d' 7.txt // 真删除数据
Sed综合练习:获取本机的IP地址
ifconfig 在 linux上可以获取本机的IP信息
ipconfig 在windows上可以获取IP地址信息
因为我们使用的是mini版,没有这个服务:
yum search ifconfig
yum install -y net-tools.x86_64
安装完毕就可以使用ifconfig 这个服务了。
符号 | 含义 | |
^ | 表示开始 | ^aaa 表示以 aaa 开始 |
$ | 表示结尾 | bbb$ 表示以 bbb 结尾 |
.* | 表示任意 | ^.* 表示以 任意字符开始 |
需求是:通过ifconfig 命令获取我的IP地址
ifconfig ens33 | grep 'inet ' | sed -e 's/inet //' | sed -e 's/ netmask.*//'
也可以这么写: \s 表示空格 * 表示0次到多次
ifconfig ens33 | grep 'inet ' | sed -e 's/\s*inet //' | sed -e 's/\s*netmask.*//'
思考:
ip addr 获取ip地址,怎么写?
ip addr | grep ens33 |grep 'inet' | sed -e 's/\s*inet //' | sed -e 's/\/.*//'
案例补充:
查找以d开头的内容:
[root@bigdata01 datas]# sed -n -e '/^d/p' 6.txt
ddd root nologin
以p开头的行前加[TAB]:注意此时的文件名字叫a
tab 键 是缩进的,比 空格 要大
$ cat a
pa:11:a
sa:32:c
app:5:b
stort:1:d
pear:4:aa
hello:3:f
$ sed '/^p/s/^/\t/' a
pa:11:a
sa:32:c
app:5:b
stort:1:d
pear:4:aa
hello:3:f
删除以a开头的行,(那么下面的输出,以a开头的行就没了)
$ sed '/^a/d' a
pa:11:a
sa:32:c
stort:1:d
pear:4:aa
hello:3:f
反向匹配(文件a中,输出只保留了a开头的行):
$ sed '/^a/!d' a
app:5:b
6、split 文件切割
创造数据:拷贝一个/etc/services
cp /etc/services $PWD
mv services big.txt
ll 查看文件的大小
按照字节进行切割:
split -b 100k big.txt
split -l 3000 big.txt
查看大小:
du -h /home/scripts/datas/xaa ==100k
ll
wc -c 文件名
删除所有的 x开头的文件
rm -rf ./x*
查看一个文件中有多少行
wc -l xaa
7、tr 替换和删除
tr 被替换的字符 新字符 是translate 的缩写
搞点数据:8.txt
laoyan
HELLO
abc12def34g
cat 8.txt | tr 'y' 'Y' #把小写 y 替换成 Y
cat 8.txt | tr [a-z] [A-Z] #把所有数据小写换成大写
删除操作:
cat 8.txt | tr -d a
使用tr 进行一个单词计数的练习
9.txt
hello,world,hadoop
hive,sqoop,flume,hello
kitty,tom,jerry,world
hadoop
第一种方案:
[root@bigdata01 scripts]# cat 9.txt | tr ',' ' '|wc -w
12
第二种方案:
将单词中的,替换为换行符
cat 9.txt | tr ',' '\n'
//接着使用排序,去重等操作
cat 9.txt | tr ',' '\n' | sort | uniq
// 接着可以进行单词重复记录的数据
cat 9.txt | tr ',' '\n' | sort | uniq -c
也可以这么写:
cat 9.txt | tr ',' '\n' | sort -u | wc -l
8、uniq 去重
uniq 命令用于检查及删除文本文件中重复出现的行,一般与 sort 命令结合使用
造一些数据10.txt
张三 98
李四 100
王五 90
赵六 95
麻七 70
李四 100
王五 90
赵六 95
麻七 70
#先排序再去重否则去重没有效果
cat 10.txt | sort | uniq
9、tee 可以将数据输送到各个文件中 ,跟一个水管一样
cat 10.txt | sort | uniq -c | tee a.txt b.txt c.txt
查看一个文件夹中所有文件的大小:
du -h *
或者
du -h -a
shell补充
[[ $num =~ ^[1-9][0-9]*$ ]]
[[ ]] 是一种更高级的条件测试语法,支持正则表达式匹配。
=~ 运算符用于正则表达式匹配。
^[1-9][0-9]*$ 表示数字的第一位数字是从 1 到 9 第二位是从 0 到 9
假设有个变量:file=/dir1/dir2/dir3/my.file.txt
${file#*/}:删掉第一个/ 及其左边的字符串:dir1/dir2/dir3/my.file.txt
${file##*/}:删掉最后一个/ 及其左边的字符串:my.file.txt
${file#*.}:删掉第一个. 及其左边的字符串:file.txt
${file##*.}:删掉最后一个. 及其左边的字符串:txt
${file%/*}:删掉最后一个 / 及其右边的字符串:/dir1/dir2/dir3
${file%%/*}:删掉第一个/ 及其右边的字符串:(空值)
${file%.*}:删掉最后一个 . 及其右边的字符串:/dir1/dir2/dir3/my.file
${file%%.*}:删掉第一个 . 及其右边的字符串:/dir1/dir2/dir3/my
标签:脚本,Shell,高级,cat,sed,awk,print,txt,root
From: https://blog.csdn.net/Yz9876/article/details/141674130