Shell 编程之文本的处理

一、cut

1.1 cut 的使用方式

cut 命令的语法格式是:cut [选项] 文件名

选项:

  • -f 列号:提取第几列
  • -d 分隔符:按照指定分隔符分割列

cut 命令默认是以制表符作为分隔符,假设我有这样一个文件,文件名是 student_info.txt,文件内容如下:

Sno	Sname	Class	Grade
1	Luffy	1001	90
2	Zoro	1001	95
3	Sanji	1001	99
4	Asee	1002	92

用 cut 命令获取指定列,效果如下:
在这里插入图片描述

当然大多数时候我们要处理的文本文件内容中并没有制表符,比如/etc/passwd,这个文件中的内容以冒号分隔,如果我们要获取某一列或者某几列,就必须指定以冒号作为分隔符。原始文件内容如下:
在这里插入图片描述
假设我们只想看用户名和 UID,可以用如下命令:cut -d ":" -f 1,3 /etc/passwd
在这里插入图片描述

下面看一个 cut 的实际应用案例:如何找到系统中所有的普通用户的用户名?

通过查看/etc/passwd不难发现,所有非系统用户所在的行都以「/bin/bash」结尾,而系统用户所在的行则没有这个特点。所以我们可以通过如下命令找到所有非系统用户所在的行:

cat /etc/passwd | grep "/bin/bash"

执行结果如下:
在这里插入图片描述
但是我们只想查看普通用户,不想查看 root 用户,所以需要对上述命令的执行结果再做一次筛选,去掉 root 用户:

cat /etc/passwd | grep "/bin/bash" | grep -v "root"

执行结果如下:
在这里插入图片描述
这样就把所有普通用户查找出来了。但是离我们的目标还差一点,我们只想查看普通用户的用户名,所以需要用 cut 命令做一下截取:

cat /etc/passwd | grep "/bin/bash" | grep -v "root" | cut -d ":" -f 1

执行结果如下:
在这里插入图片描述

1.2 cut 的缺陷

cut 命令的缺陷表现在处理多空格时。如果文件里面的某些域是由若干个空格来间隔的,那么用 cut 就有点麻烦了,因为cut 只擅长处理「以一个字符间隔」的文本内容。

比如df -h命令的输出,每一列之间是以空格为间隔的。
在这里插入图片描述
如果你想使用 cut 截取其中的某些内容就会很麻烦。

二、printf

printf 命令的语法是:printf '输出类型输出格式' 输出内容

输出类型有:

  • %ns:输出字符串。n 是数字指代输出几个字符。
  • %ni:输出整数。n 是数字指代输出几个数字。
  • %m.nf:输出浮点数。m 和 n 是数字,指代输出的整数位数和小数位数。如 8.2% 代表共输出 8 位数,其中 2 位是小数,6 位是整数。

输出格式有:

  • \a:输出警告声音
  • \b:输出退格键,也就是 Backspace 键
  • \f:清除屏幕
  • \n:换行
  • \r:回车,也就是 Enter 键
  • \t:水平输出制表符,也就是 Tab 键
  • \v:垂直输出制表符,也就是 Tab 键

比如:
在这里插入图片描述
在 awk 命令的输出中支持 print 和 printf 命令。print 会在每个输出之后自动加入一个换行符(Linux 默认没有 print 命令);printf 是标准格式输出命令,不会自动加入换行符,如果需要换行,则应手动加入换行符。

三、awk

3.1 简介

awk 命令的语法格式如下:

awk '条件1{动作1} 条件2{动作2}……' 文件名

一般使用关系表达式作为条件(Pattern):

  • x > 10 判断变量 x 是否大于 10
  • x >= 10 判断变量 x 是否大于等于 10
  • x <= 10 判断变量 x 是否小于等于 10

动作(Action):

  • 格式化输出
  • 流程控制语句

如果在动作前面不加任何条件,就说明无论如何都要执行该动作。

3.2 实践

以我们之前那个 student_info.txt 文件为例,如果想输出第 1 行和第 2 行,可以用如下命令:

awk '{printf $1"\t" $2"\n"}' /tmp/student_info.txt 

awk '{print $1"\t" $2}' /tmp/student_info.txt

这两条命令的区别是,第一个用了 printf,第二个用了 print。如果用 print,则在末尾不需要加换行符。

执行结果如下:
在这里插入图片描述
之前我们讲 cut 命令的时候说过,如果文件里面的某些域是由若干个空格来间隔的,那么用 cut 处理起来就很麻烦,但是用 awk 就可以很轻易地解决。df -h命令的输出内容的每一列之间就是用空格隔开的。

再回顾一下df -h命令的输出:
在这里插入图片描述
如果我只想显示第一行和第五行,则可以用如下命令:

df -h | awk '{print $1"\t" $5"\t"}'

执行结果如下:
在这里插入图片描述
如果现在我想获取根分区磁盘空间的占用情况,可以用如下命令:

df -h | grep "sda5" | awk '{print $5}'

在这里插入图片描述
输出的是 17%,如果我只想要前面那个 17怎么办呢?这时就可以用 cut 命令来实现了:

df -h | grep "sda5" | awk '{print $5}' | cut -d "%" -f 1

在这里插入图片描述

3.3 BEGIN

看这样一个例子:

awk 'BEGIN{print "This is a school report"} {print $2"\t" $4}' /tmp/student_info.txt

执行结果如下:
在这里插入图片描述
从这个例子中可以看出,BEGIN 是一个条件,BEGIN{动作} 的作用是在处理文本内容之前先执行指定的动作。

再看一个 BEGIN 的具体使用案例。当我们想在 awk 中手动定义分隔符时,会用这样的方式:

awk '{FS=":"} {print $1"\t" $3}' /etc/passwd #其中{FS=":"}就是定义冒号为分隔符

看一下执行结果:
在这里插入图片描述
但是我们却发现,/etc/passwd文件的第一行并没有被处理,因为 awk 在处理文本的时候是先读入第一行,然后再执行相应的动作,也就是说,当我读入第一行的时候,自定义的分隔符还没有生效,知道读入第二行的时候,自定义的分隔符才生效。为了避免这种问题,我们可以使用 BEGIN。

awk 'BEGIN{FS=":"} {print $1"\t" $3}' /etc/passwd

执行结果如下:
在这里插入图片描述

3.4 END

END 的作用正好和 BEGIN 相反,被 END 标记的动作会在 awk 处理文本内容结束之后执行。比如:

awk 'BEGIN{print "This is a school report"} {print $2"\t" $4} END{print "End"}' /tmp/student_info.txt

执行结果如下:
在这里插入图片描述

3.5 条件表达式

利用条件表达式可以实现对行(háng)的筛选。还是以之前那个 student_info.txt 文件为例,我们要想筛选出分数大于 90 的学生,可以这样写:

awk '$4>90{print $2"\t" $4}' student_info.txt

执行效果如下:
在这里插入图片描述

四、sed

sed 是一种几乎所有 UNIX 平台(包括 Linux)的轻量级流编辑器。sed 主要是用来将数据进行选取、替换、删除、新增的命令。

sed 命令的语法格式如下:

sed [选项] '[动作]' 文件名

选项:

  • -n:一般 sed 命令会把所有数据都输出到屏幕,如果加入此选择,则只会把经过 sed 命令处理的行输出到屏幕
  • -e:允许对输入数据应用多条 sed 命令编辑
  • -i:用 sed 的修改结果直接修改读取数据的文件,而不是由屏幕输出

动作:

  • a\:追加,在当前行后添加一行或多行。添加多行时,除最后 一行外,每行末尾需要用「\」代表数据未完结。
  • c\:行替换,用c后面的字符串替换原数据行,替换多行时,除最后一行外,每行末尾需用「\」代表数据未完结。
  • i\:插入,在当期行前插入一行或多行。插入多行时,除最后 一行外,每行末尾需要用「\」代表数据未完结。
  • d:删除,删除指定的行。
  • p:打印,输出指定的行。
  • s:字串替换,用一个字符串替换另外一个字符串。格式为「行范围s/旧字串/新字串/g」(和vim中的替换格式类似) 。

4.1 行数据操作

只打印第二行:

sed -n '2p' student_info.txt

执行结果如下:
在这里插入图片描述

删除第 2 行到第 4 行的数据:

sed '2,4d' student_info.txt

执行结果如下:
在这里插入图片描述

在第 2 行之后追加一行:

sed '2a hello' student_info.txt

执行结果如下:
在这里插入图片描述

在第 2 行之前插入两行:

sed '2i hello \
> world' student_info.txt

执行结果如下:
在这里插入图片描述

对第 3 行进行替换:

sed '3c onepiece' student_info.txt

执行结果如下:
在这里插入图片描述

对第 3 行中的某个字符串进行替换:

sed '3s/95/59/g' student_info.txt

执行结果如下:
在这里插入图片描述

对全文的多个字符串进行替换:

sed -e 's/1001/class1/g;s/1002/class2/g' student_info.txt #把1001换成class,把1002换成class2

执行结果如下:
在这里插入图片描述

五、sort

sort 是排序命令,命令格式如下:

sort [选项] 文件名
选项作用
-f忽略大小写
-n以数值型进行排序,默认使用字符串型排序
-r反向排序
-t指定分隔符,默认是分隔符是制表符
-k n[,m]按照指定的字段范围排序。从第n字段开始,m字段结束(默认到行尾)

最常见的用法是什么选项也不加,直接对文件内容进行排序,比如对/etc/passwd进行排序:

sort /etc/passwd

在这里插入图片描述

反向排序:

sort -r /etc/passwd

指定分隔符,并且对第 3 列进行排序:

sort -t ':' -k 3,3 /etc/passwd

执行结果如下:
在这里插入图片描述

我们发现他把第三列当成了字符串来排序,如果要想让它把第三列当成字符串来排序,则需要加-n

sort -n -t ':' -k 3,3 /etc/passwd

执行结果如下:
在这里插入图片描述

六、wc

wc 是一个统计命令,命令格式是:

wc [选项] 文件名

选项:

  • -l:只统计行数
  • -w:只统计单词数
  • -m:只统计字符数

如果什么选项都不加,那么 wc 命令就会把行数、单词数、字符数都输出出来,如果加了选项,就会输出选项对应的信息。

比如:
在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值