Shell和命令工具Shell

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

2018-09-13  本文已影响15人  中酷男

awk、sed、grep综述:

1.Linux sed 命令

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

sed主要用来:

语法

sed [-hnV][-e<script>][-f<script文件>][文本文件]
参数说明
动作说明:

实例

在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][范本样式][文件或目录...]
参数:

实例:

grep test *file

结果如下:

$ grep test *file
This is a test!
$ cat test testfile
第一列
第二列
第三列
第四列
第五列
第六行
This is a test!
$ grep -r conf /etc/acpi
/etc/acpi/events/power.conf:# ACPID config to power down machine if powerbutton is pressed, but only if
$ 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)
选项参数说明:

基本用法

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

$ 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
上一篇 下一篇

猜你喜欢

热点阅读