linux学习——shell脚本三剑客(grep、sed、awk)

awk、sed、grep综述:

  • grep 更适合单纯的查找或匹配文本
  • sed 更适合编辑匹配到的文本
  • awk 更适合格式化文本,对文本进行较复杂格式处理

1.Linux sed 命令

Linux sed命令是利用script来处理文本文件。
sed可依照script的指令,来处理、编辑文本文件。

sed主要用来:

  • 自动编辑一个或多个文件;
  • 简化对文件的反复操作;
  • 编写转换程序等。

语法

sed [-hnV][-e<script>][-f<script文件>][文本文件]
参数说明
  • -e<script>或--expression=<script> 以选项中指定的script来处理输入的文本文件。
  • -f<script文件>或--file=<script文件> 以选项中指定的script文件来处理输入的文本文件。
  • -h或--help 显示帮助
  • -n或--quit或--silent 仅显示script处理后的结果
  • -V或--version 显示版本信息
动作说明:
  • a:新增。a后面可以接字符串,而这些字符串会在新的一行出现(当前行的下一行)
  • c:取代。c的后面可以接字符串,这些字符串可以取代n1,n2之间的行
  • d:删除。d的后面一般不接其他东西
  • i:插入。i的后面可以接字符串,而这些字符串会在新的一行出现(当前行的上一行)
  • p:打印。亦即将某个选择的数据打印出来。通常p会与参数sed -n一起运行
  • s:取代。可以直接进行取代的工作。通常这个s的动作可以搭配正规表示法。例如1,20s/old/new/g

实例

在testfile文件的第四行后添加一行,并将结果输出到标准输出,在命令行提示符下输入如下命令:

sed -e 4a\newLine testfile

首先查看testfile中的内容如下:

$ cat testfile
第一行
第二行
第三行
第四行
第五行

运行sed命令,输出结果如下:

第一行
第二行
第三行
第四行
newline
第五行

以行为单位的新增/删除

将 textfile 的内容列出并且列出行号,同时,请将第2~5行删除:

$ nl testfile | sed '2,5d'
1   第一行

只删除第二行:

$ nl testfile | sed '2d'
     1  第一行
     3  第三行
     4  第四行
     5  第五行

删除从第三行开始的所有行:

$ nl testfile | sed '3,$d'
     1 第一行
     2 第二行

在第二行后(即加在第三行)加上[drink tea?]字样!

$ nl testfile | sed '2a drink tea'
     1  第一行
     2  第二行
drink tea
     3  第三行
     4  第四行
     5  第五行

如果是要在第二行前:

$ nl  testfile | sed '2i drink tea'

如果是要增加两行以上,比如在第二行后面加入两行字『drink tea or ...』与『drink beer?』:

$ nl testfile | sed '2a drink tea or ...\
> drink beer ?'
     1  第一行
     2  第二行
drink tea or ...
drink beer ?
     3  第三行
     4  第四行
     5  第五行

每个行之间都必须要以反斜杠\来进行新行的添加。所以上面的例子中,我们可以发现在第一行的最后面就有\的存在。

以行为单位的替换与显示

例如,将第2-5行的内容取代成为『No 2-5 number』:

$ nl testfile | sed '2,5c No 2-5 number'
     1  第一行
No 2-5 number

透过这个方法,我们就能将数据整行取代了。
仅列出testfile文件内的第2-4行:

$ nl testfile | sed -n '2,4p'
     2  第二行
     3  第三行
     4  第四行

可以透过这个sed的以行为单位的显示功能,就能够将某一个文件内的某些行号选择出来显示。

数据的搜寻并显示

搜索testfile有"四"关键字的行

$ nl testfile | sed '/四/p'
     1  第一行
     2  第二行
     3  第三行
     4  第四行
     4  第四行
     5  第五行

可见找到匹配行后,除了输出所有行,还会再次打印出此行。
使用-n的时候只会打印匹配的行。

$ nl testfile | sed -n '/四/p'
     4  第四行
数据的搜寻并删除

删除testfile所有包含'四'的行,其他行输出:

$ nl testfile | sed '/四/d'
     1  第一行
     2  第二行
     3  第三行
     5  第五行
数据的搜寻并执行命令

搜索testfile,找到包含'四'的行,执行后面花括号中的一组命令,每个命令之间用分号分隔,这里把'行'替换为'列',再输出这行:

$ nl testfile | sed -n '/四/{s/行/列/;p;q}'
     4  第四列

最后的q是退出。

数据的搜寻并替换

除了整行的处理模式之外,sed还可以用行为单位进行部分数据的搜寻并取代。基本上sed的搜寻与替代的与vi相当的类似,例如:

sed 's/要被取代的字符串/新的字符串/g'

利用/sbin/ifconfig查询IP:
删除IP前面部分的内容:

$ /sbin/ifconfig eth2 | grep 'inet addr' | sed 's/^.*addr://g'
192.168.80.100  Bcast:192.168.80.255  Mask:255.255.255.0

下面删除后续部分内容:

$ /sbin/ifconfig eth2 | grep 'inet addr' | sed 's/^.*addr://g' | sed 's/Bcast.*$//'
192.168.80.100  
多点编辑

一条sed命令,删除testfile第三行到末尾的行,并将"行"替换为"列"

$ nl testfile | sed -e '3,$d' | sed -e 's/行/列/'
     1  第一列
     2  第二列
直接修改文件内容(危险动作)

sed可以直接修改文件的内容,不必使用管道命令或数据量重导向。不过,由于这个动作会直接修改到原始的文件,所以请千万不要随便拿系统配置来测试。

利用sed将testfile内每一行的“行”修改为“列”:

$ sed -i 's/行/列/g' testfile
$cat testfile
第一列
第二列
第三列
第四列
第五列

利用sed直接在testfile最后一行加入"第六行":

$ sed -i '$a 第六行' testfile
$ cat testfile
第一列
第二列
第三列
第四列
第五列
第六行

由于$代表的是最后一行,而a的动作是新增,因此会增加在文件最后。
sed-i选项可以直接修改文件内容,这功能非常有帮助。举例来说,如果你有一个100万行的文件,你要在第100行加某些文字,此时使用vim可能会疯掉,因为文件太大了。此时可以使用sed直接修改/取代。

2.Linux grep 命令

Linux grep命令用于查找文件里符合条件的字符串。
grep指令用于查找内容包含指定的范本样式的文件,如果发现某文件的内容符合所指定的范本样式,预设grep指令会把含有范本样式的那一列显示出来。若不指定任何文件名称,或是所给予的文件名为"-",则grep指令会从标准输入设备读取数据。

语法

grep [-abcEFGhHilLnqrsvVwxy][-A<显示列数>][-B<显示列数>][-C<显示列数>][-d<进行动作>][-e<范本样式>][-f<范本文件>][--help][范本样式][文件或目录...]
参数:
  • -a 或 --text:不要忽略二进制的数据。
  • -A<显示行数> 或 --after-context=<显示行数>:除了显示符合范本样式的那一列之外,并显示改行之后的内容。
  • -b 或 --byte-offset:在显示符合样式的那一行之前,标示出该行第一个字符的编号。
  • -B<显示行数> 或 --before-context=<显示行数>:除了显示符合样式的那一行之外,并显示该行之前的内容。
  • -c 或 --count:计算符合样式的列数。
  • -C<显示行数> 或 --contest=<显示行数> 或 -<显示行数>:除了显示符合样式的那一行之外,并显示该行之前后的内容。
  • -d<动作> 或 --directories=<动作>:当指定要查找的是目录而非文件时,必须使用这项参数,否则grep指令将回报信息并停止动作。
  • -e<范本样式> 或 --regexp=<范本样式>:指定字符串作为查找文本内容的样式。
  • -E 或 -extended-regexp:将样式为延伸的普通表示法来使用。
  • -f<规则文件> 或 --file=<规则文件>:指定规则文件,其内容含有一个或多个规则样式,让grep查找符合规则条件的文件内容,格式为每行一个规则样式。
  • -F 或 --fixed-regexp:将样式视为固定字符串的列表。
  • -G 或 --basic-regexp:将样式视为普通的表示法来使用。
  • -h 或 -no-filename:在显示符合样式的那一行之前,不标示该行所属的文件名称。
  • -H 或 --with-filename:在显示符合样式的那一行之前,标示该行所属的文件名称。
  • -i 或 --ignore-case:忽略字符大小写的差别。
  • -I 或 --file-with-matches:列出文件内容符合指定的样式的文件名称。
  • -L 或 --file-without-match:列出文件内容不符合指定的样式的文件名称。
  • -n 或 --line-number:在显示符合样式的那一行之前,标示出该行的列数编号。
  • -q 或 --quiet 或 --silent:不显示任何信息。
  • -r 或 -recursive:此参数的效果和指定-d recurse参数相同。
  • -s 或 --no-messages:不显示错误信息。
  • -v 或 --revert-match:显示不包含匹配文本的所有行。
  • -V 或 --version:显示版本信息。
  • -w 或 --word-regexp:只显示全字符合的列。
  • `-x 或 --line-regexp':只显示全列符合的列。
  • -y:此参数的效果和指定-i参数相同。

实例:

  • 1.在当前目录中,查找后缀有file字样的文件中包含test字符串的文件,并打印出该字符串的行。此时,可以使用如下命令:
grep test *file

结果如下:

$ grep test *file
This is a test!
$ cat test testfile
第一列
第二列
第三列
第四列
第五列
第六行
This is a test!
  • 2.以递归方式查找符合条件的文件。例如,查找指定目录及其子目录(如果存在子目录的话)下所有文件中包含字符串"conf"的文件,并打印出该字符串所在行的内容,使用的命令为:
$ grep -r conf /etc/acpi
/etc/acpi/events/power.conf:# ACPID config to power down machine if powerbutton is pressed, but only if
  • 3.反向查找。前面各个例子是查找并打印出符合条件的行,通过-v参数可以打印出不符合条件行的内容。
    例如,查找当前目录中,文件名中包含test的文件中不包含test的行,此时,使用的命令为:
$ grep -v test *test*
test1.sh:#!/bin/bash
test1.sh:c1="shell"
test2.sh:#!/bin/bash
test2.sh:#或者使用以下包含文件代码
test2.sh:echo "zkn在学习$c1"
testfile:第一列
testfile:第二列
testfile:第三列
testfile:第四列
testfile:第五列
testfile:第六行

3.Linux awk 命令

awk是一种处理文本文件的语言,是一个强大的文本分析工具。
之所以叫awk是因为其取了三位创始人Alfred Aho、Peter Weinberger和Barian Kernighan的Family Name的首字母。

语法

awk [选项参数] 'script' var=value file(s)
或
awk [选项参数] -f scriptfile var=value file(s)
选项参数说明:
  • -F fs 或 --file-separator fs 指定输入文件拆分隔符,fs是一个字符串或者是一个正则表达式,如-F:
  • -v var=value 或 --asign var=value 赋值一个用户定义变量
  • -f scripfile 或 --file scriptfile 从脚本文件中读取awk命令。
  • -mf nnn 和 -mr nnnnnn值设置内在限制,-mf选项限制分配给nnn的最大块数目;-mr选项限制记录的最大数目。这两个功能是Bell实验室版awk的扩展功能,在标准awk中不适用。
  • -W compat 或 --compat ; -W traditional --traditional在兼容模式下运行awk。所以gawk的行为和标准的awk完全一样,所有的awk扩展都被忽略。
  • -W copyleft 或 --copyleft ; -W copyright 或 --copyright 打印简短的版权信息。
  • -W help 或 --help ; -W usage 或 --usage 打印全部awk选项和每个选项的简短说明。
  • -W lint 或 --lint 打印不能向传统unix平台移植的结构的警告。
  • -W lint-old 或 --lint-old 打印关于不能向传统unix平台移植的结构的警告。
  • -W posix 打开兼容模式。但有以下限制:不识别/x、函数关键字、func、换码序列以及当fs是一个空格时,将新行作为一个域分隔符;操作符**和**=不能代替=;fflush无效。
  • -W re-interval 或 --re-inerval 允许间隔正则表达式的使用,参考(grep中的Posix字符类),如括号表达式[[:alpha]]。
  • -W source program-text 或 --source program-text 使用program-text作为源代码,可与-f命令混用。
  • -W version 或 --version 打印bug报告信息的版本。

基本用法

log.txt文本内容如下:

2 this is a test
3 Are you like awk
This's a test
10 There are orange,apple,mongo

用法一:

awk '{[pattern] action}' {filenames} #行匹配语句 awk '' 只能用单引号

实例:

# 每行按空格或TAB分割,输出文本中的1/4项
$ awk '{print $1,$4}' log.txt
2 a
3 like
This's 
10 orange,apple,mongo
或
$ awk '{printf "%-8s %-10s\n",$1,$4}' log.txt
2        a         
3        like      
This's             
10       orange,apple,mongo

用法二:

awk -F #-F相当于内置变量F5,指定分割字符

实例:

### 使用","分割
$ awk -F: '{print $1,$2}' log.txt
2 this is a test 
3 Are you like awk 
This's a test 
10 There are orange,apple,mongo 
### 或者使用內建变量
$ awk 'GEGIN{FS=","}{print $1,$2}' log.txt
2 this
3 Are
This's a
10 There
### 使用多个分隔符。先使用空格分割,然后对分割结果再使用","分割
$ awk -F '[ ,]' '{print $1,$3,$5}' log.txt
2 is test
3 you awk
This's test 
10 are apple

用法三:

awk -v #设置变量

实例:

$ awk -va=1 '{print $1,$1+a}' log.txt
2 3
3 4
This's 1
10 11
$ awk -va=1 -vb=s '{print $1,$1+a,$1b}' log.txt
2 3 2s
3 4 3s
This's 1 This'ss
10 11 10s

用法四:

awk -f {awk脚本} {文件名}

实例:

$ awk -f cal.awk log.txt

运算符

运算符 描述
= += -= *= /= %= ^= **= 赋值
?: C条件表达式
|| 逻辑或
&& 逻辑与
~ ~! 匹配正则表达式和不匹配正则表达式
< <= > >= != == 关系运算符
空格 连接
+ - 加和减
* / % 乘、除和求余
+ - ! 一元加、减和逻辑非
^ *** 求幂
++ -- 增加或减少,作为前缀或后缀
$ 字段引用
in 数组成员

过滤第一列大于2的行:

$ awk '$1>2' log.txt
3 Are you like awk
This's a test
10 There are orange,apple,mongo

获取第一列等于2的行:

$ awk '$1==2' log.txt
2 this is a test

获取第一列大于2并且第二列等于'Are'的行:

$ awk '$1>2 && $2=="Are" ' log.txt
3 Are you like awk

內建变量

变量 描述
$n 当前记录的第n个字段,字段间由FS分隔
$0 完整的输入记录
ARGC 命令行参数的数目
ARGIND 命令行中当前文件的位置(从0开始算)
ARGV 包含命令行参数的数组
CONVFMT 数字转换格式(默认%.6g)ENVIRON环境变量关联数组
ERROR 最后一个系统错误的描述
FIELDWIDTHS 字段宽度列表(用空格键分隔)
FILENAME 当前文件名
FNR 个文件分别计数的行数
FS 字段分隔符(默认是任何空格)
IGNORECASE 如果为真,则进行忽略大小写的匹配
NF 一条记录的字段的数目
NR 已经读出的记录数,就是行号,从1开始
OFMT 数字的输出格式(默认是%.6g)
OFS 输出记录分隔符(输出换行符),输出时用指定的符号代替换行符
ORS 输出记录分隔符(默认是一个换行符)
RLENGTH 由match函数所匹配的字符串的长度
RS 记录分隔符(默认是一个换行符)
RSTART 有match函数所匹配的字符串的第一个位置
SUBSEP 数组下标分隔符(默认值是/034)

使用正则字符串匹配

输出第二列包含"th"的行,并打印第二列和第四列

$ awk '$2 ~ /th/ {print $2,$4}' log.txt
this a

~表示模式开始,//中是模式
输出包含"re"的行

$ awk '/re/' log.txt
3 Are you like awk
10 There are orange,apple,mongo

忽略大小写

$ awk 'BEGIN{IGNORECASE=1} /this/' log.txt #大写和小写的this均匹配出来了
2 this is a test
This's a test

模式取反

$ awk '$2 !~ /th/ {print $2,$4}' log.txt
Are like
a 
There orange,apple,mongo
$ awk '!/th/ {print $2,$4}' log.txt
Are like
a 
There orange,apple,mongo

awk脚本

关于awk脚本,我们需要注意两个关键词BEGINEND

  • BEGIN{这里面放的是执行前的语句}
  • END{这里面放的是处理完所有的行后要执行的语句}
  • {这里面放的是处理每一行时要执行的语句}
    假设有这么一个文件(学生成绩表):
$ cat score.txt
Marry   2143 78 84 77
Jack    2321 66 78 45
Tom     2122 48 77 71
Mike    2537 87 97 95
Bob     2415 40 57 62

我们的awk脚本如下:

$ cat cal.awk
#!/bin/awk -f
#运行前
BEGIN {
    math = 0
    english = 0
    computer = 0
    printf "NAME   NO.    MATH 
   ENGLISH   COMPUTER   TOTAL\n"
}
#运行中
{
    math+=$3
    english+=$4
    computer+=$5
    printf "%-6s %-6s %4d %8d %8d %8d\n",$1,$2,$3,$4,$5,$3+$4+$5
}
#运行后
END{
    printf "TOTAL:%10d %8d %8d \n",math,english,computer
    printf "AVERAGE:%10.2f %8.2f %8.2f\n",math/NR,english/NR,computer/NR
}

下面看执行结果:

$ awk -f cal.awk score.txt
NAME   NO.    MATH   ENGLISH    COMPUTER    TOTAL
Marry  2143     78       84       77      239
Jack   2321     66       78       45      189
Tom    2122     48       77       71      196
Mike   2537     87       97       95      279
Bob    2415     40       57       62      159
TOTAL:       319      393      350 
AVERAGE:     63.80    78.60    70.00

另外一些实例

awk的hello world程序为:

BEGIN { print "Hello,World!"}

计算文件大小:

$ ls -l *.txt | awk '{sum+=$5} END {print sum}'
192

从文件中找出长度大于20的行:

$ awk 'length>20' log.txt
10 There are orange,apple,mongo

打印九九乘法口诀:

$ seq 9 | sed 'H;g' | awk -v RS=''  '{for(i=1;i<=NF;i++)printf("%dx%d=%d%s",i,NR,i*NR,i==NR?"\n":"\t")}'
1x1=1
1x2=2   2x2=4
1x3=3   2x3=6   3x3=9
1x4=4   2x4=8   3x4=12  4x4=16
1x5=5   2x5=10  3x5=15  4x5=20  5x5=25
1x6=6   2x6=12  3x6=18  4x6=24  5x6=30  6x6=36
1x7=7   2x7=14  3x7=21  4x7=28  5x7=35  6x7=42  7x7=49
1x8=8   2x8=16  3x8=24  4x8=32  5x8=40  6x8=48  7x8=56  8x8=64
1x9=9   2x9=18  3x9=27  4x9=36  5x9=45  6x9=54  7x9=63  8x9=72  9x9=81
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,454评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,553评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,921评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,648评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,770评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,950评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,090评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,817评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,275评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,592评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,724评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,409评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,052评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,815评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,043评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,503评论 2 361
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,627评论 2 350

推荐阅读更多精彩内容