利用命令行快速处理文件

1、Shell里的循环与判断结构

for循环:

1
for i in `cat 1.txt`;do command;done

while循环:

1
while [表达式];do command;done

if结构:

1
2
3
4
5
if [条件];then
command
else
command
fi

2、shell三剑客

(sed和awk部分参考了黑马程序员武汉中心在线教程文件2019全新Shell脚本从入门到精通教程_哔哩哔哩_bilibili

grep

语法格式:

1
grep [options] "patten" filename1 filename2 filename3     #打印包含patten的行

常用options:

选项 说明
-v 反向输出
–color=auto 标记匹配颜色
-E 使用正则表达式
-o 只输出匹配部分
-c 统计包含匹配字符的行数
-n 输出匹配内容及其行号
-b 打印匹配模式位于行的位置
-l 搜索多个文件,并查找匹配文本在拿个文件中
. -r 在多级目录中查找
-i 忽略大小写
-e 匹配两个patten
-q 不输出任何内容,成功返回0,失败则返回非0值
-An 打印匹配模式之后的n行
-Bn 打印匹配模式之前的n行
-Cn 打印匹配模式上下游各n行
1
2
3
4
5
6
eg: 
echo gun is not unix | grep -b -o "not" #输出 7:not
grep -l "patten" file1 file2 file3 #输出文件名
grep "patten" . -r -n #.代表当当前目录
grep -e "patten1" -e "patten2" filename
grep -q "patten" filename

另:Linux xargs命令(结合管道使用):

1
2
eg:
cat url-list.txt | xargs wget -c #文件包含多个URL,使用xargs下载

xargs命令的详细用法参考Linux xargs 命令 | 菜鸟教程 (runoob.com)

sed

语法格式:

1
sed [options] '定位+处理动作' 文件名

常用options:

选项 说明 备注
-e 进行多项(多次)编辑
-n 取消默认输出 不自动打印模式空间
-r 使用扩展正则表达式
-i 原地编辑(修改源文件)
-f 指定sed脚本的文件名

常用处理(在单引号里):

动作 说明 备注
‘p’ 打印
‘i’ 在指定行之前插入内容 类似vim里的大写O
‘a’ 在指定行之后插入内容 类似vim里的小写o
‘c’ 替换指定行所有内容
‘d’ 删除指定行

对文件进行增、删、改、查操作

1
sed -n '1,5p'  a.txt				#打印1到5行
1
sed -n '$p' a.txt 					#打印最后1行
1
sed '5a99999' a.txt 	#文件第5行下面增加内容
1
sed '/^uucp/ihello'	#以uucp开头行的上一行插入内容
1
2
sed '1,5chello world' a.txt 	#替换文件1到5号内容为hello world
sed '/^user01/c888888' a.txt #替换以user01开头的行
1
sed '$d' a.txt			#删除文件最后一行
1
sed -n '1,5s/^/#/p' a.txt  #注释掉文件的1-5行内容
1
sed -n 's/root/ROOT/gp' 1.txt   #替换1.txt文件中所有的root为ROOT

sed结合正则使用

正则 说明 备注
/key/ 查询包含关键字的行 sed -n '/root/p' 1.txt
/key1/,/key2/ 匹配包含两个关键字之间的行 sed -n '/\^adm/,/^mysql/p' 1.txt
/key/,x 从匹配关键字的行开始到==文件第x行==之间的行(包含关键字所在行) sed -n '/^ftp/,7p'
x,/key/ 从文件的第x行开始到与关键字的匹配行之间的行
x,y! 不包含x到y行
/key/! 不包括关键字的行 sed -n '/bash$/!p' 1.txt

awk

awk是unix下的一个工具,也是一门语言,支持条件判断和循环语句(如for或while),是数据文件的列处理工具

1
awk [options] '命令部分' filename

常用选项:

选项 说明
-F 定义分隔符,默认为空格
-v 定义变量并赋值(awk中调用变量无需加$符号)

命令部分:

1
2
3
4
5
6
7
8
9
10
11
12
a)正则表达式或地址位置    
'/root/{awk语句}'
'NR==1,NR==5{awk语句}' #sed中:'1,5p'
'/^root/,/^ftp/{awk语句}' #sed中:'/^root/,/^ftp/p'
b)
{awk语句1;awk语句2}
注:awk命令语句间用分号间隔
c)
BEGIN...END....
'BEGIN{awk语句};{处理中};END{awk语句}'
'BEGIN{awk语句};{处理中}'
'{处理中};END{awk语句}'

awk内部相关变量

变量 变量说明 备注
$0 当前处理行的所有记录
$1,$2,$3…$n 文件中每行以==间隔符号==分割的不同字段 awk -F: '{print $1,$3}'
NF 当前记录的字段数(列数) awk -F: '{print NF}'
$NF 最后一列 $(NF-1)表示倒数第二列
FNR/NR 行号
FS 定义间隔符 'BEGIN{FS=":"};{print $1,$3}'
OFS 定义输出字段分隔符,==默认空格== 'BEGIN{OFS="\t"};print $1,$3}'
RS 输入记录分割符,默认换行 'BEGIN{RS="\t"};{print $0}'
ORS 输出记录分割符,默认换行 'BEGIN{ORS="\n\n"};{print $1,$3}'
FILENAME 当前输入的文件名

awk工作原理

awk -F: '{print $1,$3}' /etc/passwd

1
2
3
4
5
6
7
8
9
10
11
awk使用一行作为输入,并将这一行赋给内部变量$0,每一行也可称为一个记录,以换行符(RS)结束

每行被间隔符**:**(默认为空格或制表符)分解成字段(或域),每个字段存储在已编号的变量中,从$1开始

问:awk如何知道用空格来分隔字段的呢?

答:因为有一个内部变量FS来确定字段分隔符。初始时,FS赋为空格

awk使用print函数打印字段,打印出来的字段会以空格分隔,因为\$1,\$3之间有一个逗号。逗号比较特殊,它映射为另一个内部变量,称为输出字段分隔符OFS,OFS默认为空格

awk处理完一行后,将从文件中获取另一行,并将其存储在$0中,覆盖原来的内容,然后将新的字符串分隔成字段并进行处理。该过程将持续到所有行处理完毕

格式化输出printprintf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
print函数		类似echo "hello world"
# date |awk '{print "Month: "$2 "\nYear: "$NF}'
# awk -F: '{print "username is: " $1 "\t uid is: "$3}' /etc/passwd


printf函数 类似echo -n
# awk -F: '{printf "%-15s %-10s %-15s\n", $1,$2,$3}' /etc/passwd
# awk -F: '{printf "|%15s| %10s| %15s|\n", $1,$2,$3}' /etc/passwd
# awk -F: '{printf "|%-15s| %-10s| %-15s|\n", $1,$2,$3}' /etc/passwd

awk 'BEGIN{FS=":"};{printf "%-15s %-15s %-15s\n",$1,$6,$NF}' a.txt

%s 字符类型 strings %-20s
%d 数值类型
占15字符
- 表示左对齐,默认是右对齐
printf默认不会在行尾自动换行,加\n