shell编程——字符截取和替换命令

1.cut列提取命令

cut [选项] 文件名
选项:
	-f 列号:提取第几列
	-d 分隔符:按照指定分隔符分隔列
	-c 字符范围:不依赖分隔符来区分列,而是通过字符范围(行首为0)来进行字段提取。“n-”表示从第n个字符到行尾;“n-m”从第n个字符到第m个字符;“-m”表示从第1个字符到第m个字符

cut命令默认分隔符是制表符,也就是“tab”键,不过对空格符支持的不好

2.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键

在这里插入图片描述
如上格式的txt文件,我们按字符串进行输出
在这里插入图片描述
如果不指定输出格式,则会把所有输出内容连在一起输出。其实文本的输出本身就是这样的,cat等文本输出命令之所以可以按照格式漂亮的输出,那是因为cat命令已经设定了输出格式。那么为了用printf输出合理的格式,应该这样做:
在这里插入图片描述

awk基本使用

awk '条件1{动作1} 条件2{动作2}...' 文件名
条件(Pattern) :
	一般使用关系表达式作为条件。这些关系表达式非常多,例如:
	x > 10	判断变量x是否大于10
	x==y	判断变量x是否等于变量y
	A~B		判断字符串A中是否包含能匹配B表达式的子字符串
	A!~B	判断字符串A中是否不包含能匹配B表达式的子字符串
动作(Action) :
	格式化输出
	流程控制语句

我们这里先来学习awk基本用法,也就是只看看格式化输出动作是干什么的。至于条件类型和流程控制语句我们在后面再详细介绍。那看看这个例子吧:

awk '{printf $2 "\t" $6 "\n"}' student.txt
# 输出第二列和第六列

在这里插入图片描述
在这里插入图片描述

awk的条件

条件的类型条件说明
awk保留字BEGIN在awk程序一开始时,尚未读取任何数据之前执行。BEGIN后的动作只在程序开始时执行一次
END在awk程序处理完所有数据,即将结束时执行。END后的动作只在程序开始时执行一次
关系运算符>大于
<小于
>=大于等于
<=小于等于
==等于。用于判断两个值是否相等,如果是给变量赋值,请使用“=”号
!=不等于
A~B判断字符串A中是否包含能匹配B表达式的子字符串
A!~B判断字符串A中是否不包含能匹配B表达式的子字符串
正则表达式/正则/如果在“//”中可以写入字符,也可以支持正则表达式
  • BEGIN
    BEGIN是awk的保留字,是一种特殊的条件类型。BEGIN的执行时机是“在awk程序一开始时,尚未读取任何数据之前执行”。一旦BEGIN后的动作执行一次,当awk开始从文件中读入数据, BEGIN的条件就不再成立,所以BEGIN定义的动作只能被执行一次。例如:
awk 'BEGIN{printf "This is a transcript \n"} {print $2 "\t" $6 "\n"}' student.txt
#awk命令只要检测不到完整的单引号不会执行,所以这个命令的换行不用加入“\”,就是一行命令
#这里定义了两个动作
#第一个动作使用BEGIN条件,所以会在读入文件数据前打印"This is a transcript"(只会执行一次)
#第二个动作会打印文件的第2列和第6列

在这里插入图片描述

  • END
    END也是awk保留字,不过刚好和BEGIN相反。END是在awk程序处理完所有数据,即将结束时执行。END后的动作只在程序结束时执行一次
  • 关系运算符
    举几个例子看看关系运算符。假设我想看看平均成绩大于等于87分的学员是谁,就可以这样输入命令:
cat student.txt | grep -v Name | awk '$6 >=87 {printf $2 "\n"}'
#使用cat输出文件内容,用grep取反包含“Name”的行
#判断第六字段(平均成绩)大于等于87分的行,如果判断式成立,则打印第六列(学员名)

在这里插入图片描述
加入了条件之后,只有条件成立动作才会执行,如果条件不满足,则动作则不运行。通过这个实验,大家可以发现,虽然awk是列提取命令,但是也要按行来读入的。这个命令的执行过程是这样的:

  1. 如果有BEGIN条件,则先执行BEGIN定义的动作
  2. 如果没有 BEGIN条件,则读入第一行,把第一行的数据依次赋予$0、$1、 $2等变量。其中$0
    代表此行的整体数据,$1 代表第一字段,$2 代表第二字段
  3. 依据条件类型判断动作是否执行。如果条件符合,则执行动作,否则读入下一行数据。如果没有条件,则每行都执行动作
  4. 读入下一行数据,重复执行以上步骤

再举个例子,如果想看看Sc用户的平均成绩呢?

awk '$2~/Sc/ {printf $6 "\n"}' student.txt
#如果第二字段中包含有“Sc”字符,则打印第六段数据

这里要注意在awk中,使用“/ /”包含的字符串,awk命令才会查找。也就是说字符串必须用“/ /”包含,awk命令才能正确识别
在这里插入图片描述

awk内置变量

awk内置变量作用
$0代表目前awk所读入的整行数据。我们已知awk是一行一行读入数据的,$0就代表当前读入行的整行数据
$n代表目前读入行的第n个字段
NF当前行拥有的字段(列)总数
NR当前awk所处理的行,是总数据的第几行
FS用户定义分隔符。awk默认分隔符是任何空格,如果想要使用其他分隔符(如“:”),就需要FS变量定义
ARGC命令行参数个数
ARGV命令行参数数组
FNR当前文件中的当前记录数(对输入文件起始为1)
OFMT数值的输出格式(默认为%.6g)
OFS输出字段的分隔符(默认为空格)
ORS输出记录分隔符(默认为换行符)
RS输入记录分隔符(默认为换行符)
cat /etc/passwd | grep "/bin/bash" | awk '{FS=":"} {printf $1 "\t" $3 "\n"}'
# 查询可以登录的用户的用户名和UID

在这里插入图片描述

我们发现第一行打印了整行,后面的行正确打印说明第一行没有把冒号作为分隔符打印,这是为什么呢?
awk先把第一行的数据读到awk中,依次赋予$0、$1、 $2等变量,再进行{print}处理,这时才发现分隔符是冒号,这时只能按照默认分隔符为空格的方式打印,但是第一行没空格,所以只能整体打印;到了第二行,先知道分隔符是冒号,所以依次赋予$0、$1、 $2等变量前先按照冒号分割,所以才正确打印,那怎么才能解决这个问题?

cat /etc/passwd | grep "/bin/bash" | awk 'BEGIN {FS=":"} {printf $1 "\t" $3 "\n"}'
#先执行BEGIN,将冒号作为分隔符,再赋值打印

在这里插入图片描述

cat /etc/passwd | grep "/bin/bash" | awk 'BEGIN {FS=":"} {printf $1 "\t" $3 "\t 行号:" NR "\t 字段数:" NF "\n"}'
# 开始执行{分隔符是:},{输出第一字段和第三字段,输出行号(NR值),字段数(NF值)}

在这里插入图片描述

3.sed命令

sed主要是用来将数据进行选取、替换、删除、新增的命令

sed [选项][动作]’ 文件名
选项作用
-n一般sed命令会把所有数据都输出到屏幕,如果加入此选项,则只会把经过sed命令处理的行输出到屏幕
-e允许对输出数据应用多条sed命令编辑
-f 脚本文件名从sed脚本中读入sed操作,和awk命令的-f非常类似
-r在sed中支持扩展正则表达式
-i用sed的修改结果直接修改读取数据的文件,而不是由屏幕输出
动作作用
a \追加,在当前行后添加一行或多行。添加多行时,除最后一行外,每行末尾需要用“\”代表数据未完结
c \行替换,用c后面的字符串替换原数据行,替换多行时,除最后一行外,每行末尾需用“\”代表数据未完结
I \插入,在当期行前插入一行或多行。插入多行时,除最后一行外,每行末尾需用“\”代表数据未完结
d删除,删除指定的行
p打印,输出指定的行
s字符串替换,用一个字符串替换另外一个字符串。格式为“行范围s/旧字符串/新字符串/g”(和vim中的替换格式类似)

如何查看文件中的某一行

在这里插入图片描述

如何删除文件的数据

在这里插入图片描述

sed -i '2,4d' student.txt
# 在删除2~4行的同时也操作原始文本数据,是真删除
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值