文章目录
一、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 命令就会把行数、单词数、字符数都输出出来,如果加了选项,就会输出选项对应的信息。
比如: