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

awk、sed、grep综述:

grep 更适合单纯的查找或匹配文本

sed 更适合编辑匹配到的文本

awk 更适合格式化文本,对文本进行较复杂格式处理

1.Linux sed 命令

Linux sed命令是利用script来处理文本文件。

sed可依照script的指令,来处理、编辑文本文件。

sed主要用来:

自动编辑一个或多个文件;

简化对文件的反复操作;

编写转换程序等。

语法

sed [-hnV][-e

参数说明

-e

-f

-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 nnn 对nnn值设置内在限制,-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脚本,我们需要注意两个关键词BEGIN和END。

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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值