cut
格式:
cut [选项] 文件名
参数:
-f
列号: 提取第几列
-d
分隔符: 按照指定分隔符分割列
我们来演示一下,我们先建立一个文件,student.txt:
ID NAME GENDER MARK
1 liuwejia M 61
2 lilingjie W 96
3 zhangsan M 88
注意,中间是tab制表符,而不是空格,否则cut命令是没法正确截取的。
cut -f 2 student.txt
:提取第二列。cut -f 2,3 student.txt
:提取第二列和第三列。cut -d ":" -f 1,3 etc/passwd
:但是cut命令还是有它的局限性,我们有些时候是用空格进行格式对齐的,这个时候cut就无能为力了,所以这个时候我们需要学习下面更强大也更繁琐的awk
命令。
printf
命令在学习awk
命令之前,我们先学习printf
,格式化输出命令。
格式:
printf '输出类型输出格式' 输出内容
输出类型:
%ns
:输出字符串。n是数字指代输出几个字符。
%ni
:输出整数。n是数字指代输出几个数字。
%m.nf
:输出浮点数。m和n是数字,指代输出的整数 位数和小数位数。如%8.2f代表共输出8位数, 其中2位是小数,6位是整数。
输出格式:
\a
: 输出警告声音
\b
: 输出退格键,也就是Backspace键
\f
: 清除屏幕
\n
: 换行
\r
: 回车,也就是Enter键
\t
: 水平输出退格键,也就是Tab键
\v
: 垂直输出退格键,也就是Tab键
我们演示一下:
printf %s 1 2 3 4 5 6
printf %s %s %s 1 2 3 4 5 6
printf '%s %s %s' 1 2 3 4 5 6
printf '%s %s %s\n' 1 2 3 4 5 6
我们先新建一个文件,student.txt:
ID Name PHP Linux MySql Average
1 lwj 82 95 86 87.66
2 llj 99 99 99 99.00
3 zs 95 97 96 96.00
printf '%s' $(cat student.txt)
:不调整输出格式printf '%s\t %s\t %s\t %s\t %s\t %s\t \n' $(cat student.txt)
:调整格式输出在awk命令的输出中支持print
和printf
命令
awk
命令格式:
awk ‘条件1{动作1} 条件2{动作2}…’ 文件名
条件(pattern):
一般使用关系表达式作为条件。
x > 10 :判断变量 x是否大于10
x>=10 :大于等于
x<=10 :小于等于
动作(action):
格式化输出;
流程控制语句。
首先我们还是用上面的文件为例,我们提取第二列的姓名和第六列的成绩平均值。
awk '{printf $2"\t"$6"\n"}' student.txt
其中$2
表示第二列,$6
表示第六列。
我们再举一个例子,我们知道df -h
命令是查看当前系统的磁盘文件占用状况的:
我们可以看到根分区的占用情况是32%,我们假设一种场景,我们写一个程序,它会两个小时执行一次,判断根分区的占用情况,如果占用大于80%,我们就报警。所以现在我们需要得到32这个数字,为了这个目的,我们可以进行下面的操作:
df -h
,获取磁盘文件系统的信息。grep sda3
;awk '{print $5}'
;cut -d "%" -f 1
我们把上面的操作用管道符连接起来,得到:
df -h | grep sda3 |awk '{print $5}' | cut -d "%" -f 1
awk 'BEGIN{print "gender!"} {printf $2"\t"$6"\n"}' student.txt
BEGIN的作用是在执行真正的脚本之间,先进行的动作,我们这里就是先输出一句话:
我们先做一个实验,
awk '{FS=":"} {printf $1 "\t" $3 "\n"}' /etc/passwd
其中FS的作用是指定分隔符,我们知道默认是以空格和制表符为分隔符的,而我们可以使用FS来指定分隔符,FS也称之为FS内置变量。也就是我们想提取/etc/passwd文件的第一列和第三列,指定用冒号分割,我们看一下结果:
我们看到大部分都是符合我们的预期的,但是第一行却没有分割,这就是因为命令是先读取了第一行字符,完成操作之后,才读取了FS=":"
,所以后面的都正确分割,唯独第一行不可以。这个时候,我们就可以使用BEGIN了,我们在读取之前就指定分隔符,我们看一下:awk 'BEGIN{FS=":"} {printf $1 "\t" $3 "\n"}' /etc/passwd
我们看到,这样就没有问题了。
有BEGIN,那么相应的就有END。意思也就是在执行的结束要执行的动作。
awk 'END{print "END!"} {print $2}' student.txt
cat student.txt | grep -v Name | awk '$6 >= 90 {printf $2 "\n" }'
这一行命令的意思就是去掉标题行,然后判断平均成绩是否大于90,大于的话就输出第二列,也就是姓名:
sed
是一种几乎包括在所有 UNIX 平台(包括 Linux)的轻量级流编辑器。sed主要是用来将数据进行选取、替换、删除、新增的命令。
格式:
sed [选项] '[动作]' 文件名
选项:
-n
: 一般sed命令会把所有数据都输出到屏幕 , 如果加入此选择,则只会把经过sed命令处 理的行输出到屏幕。
-e
: 允许对输入数据应用多条sed命令编辑
-i
: 用sed的修改结果直接修改读取数据的文件, 而不是由屏幕输出
动作:
a \
: 追加,在当前行后添加一行或多行。添加多行时,除最后 一行 外,每行末尾需要用“\”代表数据未完结。
c \
: 行替换,用c后面的字符串替换原数据行,替换多行时,除最 后一行外,每行末尾需用“\”代表数据未完结。
i \
: 插入,在当期行前插入一行或多行。插入多行时,除最后 一行 外,每行末尾需要用“\”代表数据未完结。
d
: 删除,删除指定的行。
p
: 打印,输出指定的行。
s
: 字串替换,用一个字符串替换另外一个字符串。格式为“行范围s/旧字串/新字串/g
”(和vim中的替换格式类似)。
不加-n参数,我们可以试一下:sed '2p' student.txt
我们看到,他只是把第二行重复打印了一遍,整个文档也打印了一遍。我们只想得到第二行的数据,就可以加上-n参数:sed -n '2p' student.txt
我们也可以删除第二行到第四行的数据,但不修改文件本身:sed '2,4d' student.txt
在第二行后追加hello:sed '2a hello' student.txt
如果想在第二行之前插入两行数据,就需要:
sed '2i hello\
> world' student.txt
我们也可以做数据替换:sed '2c No such person' student.txt
在第三行中,把99换成100:sed '3s/99/100/g' student.txt
但是以上所有我们尝试的操作都是在修改命令输出的结果,而并没有影响原来的文件本身,我们可以加入-i参数来保存我们的修改:sed -i '3s/99/100/g' student.txt
我们再次尝试使用-e参数来尝试执行多个条件:sed -e 's/llj/LLJ/g ; s/zs/wingman/g' student.txt
,分别把llj换成LLJ,把zs换成wingman:
END.