利用命令行快速处理文件
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
|
常用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 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中,覆盖原来的内容,然后将新的字符串分隔成字段并进行处理。该过程将持续到所有行处理完毕
|
格式化输出print
和printf
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
|