Shell脚本的高级部分

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,n2fields分割以后显示第几段内容, 使用 , 分割
参数英文含义
-ccharacters按字符选取内容

范围控制

范围含义
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

对字符串进行排序,去重

参数英文含义
-uunique去掉重复的
将 1.txt 中 第二列数据,倒序排列
[root@bigdata01 datas]# cut -d ":" -f 2 1.txt | sort -r
iii
ggg
ddd
aaa

数值类型操作

对数值类型进行的操作

参数英文含义
-nnumeric-sort按照数值大小排序
-rreverse使次序颠倒

准备数据:3.txt

1
3
5
7
11
2
4
6
10
8
9

对成绩进行排序

参数英文含义
-tfield-separator指定字段分隔符
-kkey根据哪一列排序
造数据: 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

如果只想显示某一些数据:

参数英文含义
-cbytes字节数
-wwords单词数
-llines行数
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获取 当前行 内容
NFfield表示当前行共有多少个字段
$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 可选项 目标文件对目标文件 进行 过滤查询 或 替换

可选参数

可选项英文含义
pprint打印
$代表 最后一行
-n仅显示处理后的结果
-eexpression根据表达式 进行处理

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修改内容
参数英文含义
iinsert目标前面 插入内容
aappend目标后面 追加内容
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

  • 22
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值