Linux三剑客

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Linux三剑客相关的知识,希望对你有一定的参考价值。

awk

awk推荐去看朱双印的博客“awk从放弃到入门”,写的真的很好,本文的awk就总结于它。

 

awk其实是一门编程语音,它支持条件判断、数组、循环等功能。所以,我们也可以把awk理解成一个脚本语言解释器

1awk基础

1.1、普通模式

awk option ‘program’ file1file2

技术分享图片

1.2、特殊模式

技术分享图片

1)  BEGIN和END模块只能有一个。中间的pattern匹配,可以有多个

NR==2{print $1}NR==5{print $1}

2)  BEGIN模块,代表awk在处理文本前要做的事。即使不接收文件名,仅仅使用BEGIN模块打印,也能正常输出

awk ‘BEGIN {print “111”,”222”}’

3)  END模块,代表awk在处理文本后要做的事

awk ‘{print $1,$2} END{print ‘333’,’444’}’test

1.3、内置变量

变量名

属性

备注

$0

当前记录。即一整行


$1~$n

当前记录的第n个字段

awk   ‘{print “str:”$1}’

FS

输入字段分隔符,默认space

awk   –F ‘:’

awk   –v FS=’:’

RS

输入记录分隔符,默认为

如果RS=””,会以空白行分隔

OFS

输出字段分隔符,默认space


ORS

输出的记录分隔符,默认


NF

当前记录中的字段个数,即多少列


NR

行号,从1开始


FNR

各文件分别显示行号


FILENAME

当前文件名

awk   ‘{print FILENAME,$0}’

ARGC

命令行参数的个数


ARGV

数组,保存的是命令行所给定的参数

ARGV[0]awk,单引号中的不算参数,处理的文件是参数

技术分享图片

1.4、自定义变量

awk除了使用内置变量,还可以自己定义变量。

方法一:-v varname=value 变量名区分字符大小写。-v:设置变量

方法二:在program中定义

1-v 定义

技术分享图片


2、在program定义

技术分享图片


2printf

awk本身负责文本切割,printf动作则负责格式格式化文本。在了解awkprintf动作前,需要首先了解printf命令

2.1shellprintf命令

shell中,echoprintf都是输出文本的命令。echo输出的字符串,会自动在末尾加上

printf不会。printf的作用是按照我们指定的格式输出文本,所以 ,也需要我们自己指定

echoprintf

技术分享图片

注意看3printf的优势就在于,可以用格式替换符,帮我们处理一长串的str

 

替换符号

格式替换符

名称

含义

%s

字符串

%f

浮点格式

%b

对应的参数包含转义字符时,对应的转义字符会被转义

%c

ASCII字符,显示对应参数的第一个字符

%d%i

十进制整数

%o

不带正负号的八进制值

%u

不带正负号的十进制值

%x

不带正负号的十六进制值,用af表示1015

%X

不带正负号的十六进制值,用AF表示1015

%%

表示‘%’本身

 

转义字符

名称

含义

a

警告字符,常为ASCIIBEL字符



后退

c

不显示输出结果中任何结尾的换行字符(%b格式下的参数字符串依然有效)

f

换页(formfeed

换行

回车

水平制表符

v

垂直制表符

\

”本身

ddd

表示13位数八进制值得字符串,仅在字符格式串中有效

ddd

表示13位数八进制值得字符串

 

修饰符

参数

含义

%7s

7就代表当前替换符对应的输出长度为7个字符宽,不足补齐,超出也正常显示

%-7s

-”,表示左对齐,不加时,是右对齐

%+5d

正数会自动变为+num

%12.3f

.3”表示保留小数点后三位,%f默认是小数点后6

%12.5d

.5”表示整数的长度,不足用0补齐

 

 

例子
技术分享图片技术分享图片

2.2awkprintf动作

awkprintf动作与shellprintf命令很像,只是要注意几点:

1)  使用printf动作输出的文本不会换行,要自己手动加

2)  使用printf动作时,“指定的格式”与“被格式化的文本”间,要用“逗号”隔开

3)  使用printf动作,“格式替换符”与“被格式化的文本”数量一一对应

例子

技术分享图片

awk -v FS=':' 'BEGIN{printf "%-10s %s ","用户名称","用户ID"} {printf "%-10s %s ",$1,$3}' /etc/passwd

用户名称         用户ID

root             0

bin              1

3awk模式(Pattern

3.1grepawk的正则对比

grep ‘^root’/etc/passwd

awk ‘/^root/{print $0}’ /etc/passwd

技术分享图片

技术分享图片技术分享图片

 

3.2awk正则的注意点

1awk命令中的正则是“扩展正则表达式”

2)当使用{x,y}[[:space]],这种正则时,要加上参数—posix

3)注意对“”和“.”转义

 

3.3awk的行范围模式

技术分享图片

两个正则的就是行范围模式,从正则1匹配的行开始,到正则2匹配的行结束

正则匹配符

~

匹配后面的正则。’$1~/pattern/’

!~

不匹配后面的正则’$1!~/pattern/’

 

3.4、例子



技术分享图片技术分享图片



4awk动作总结

4.0、动作拆分

技术分享图片

 

上图的动作分为两个部分:

1)  红线标注:最外侧的括号“{}”。“组合语句”类型的动作,将多个代码组合成代码块

2)  蓝线标注:“print $0”。print是“输出语句”类型的动作

例子


技术分享图片技术分享图片

4.1if动作

技术分享图片

如果if对应的{},只有一条命令,可以省略{}

4.2for动作

技术分享图片

4.3while动作

技术分享图片

4.4do…while动作

do…while循环无论是否满足while的条件,都会先执行一次do里的命令

# 打印一遍test

技术分享图片

# 打印5遍test

技术分享图片

4.5cotinuebreak

# 1~5,不打印3

技术分享图片

# 打印1~3

技术分享图片

4.6exit

awk中,exit表示跳过后序所有动作,直接执行END内的命令。如果没有END模式,则会直接结束awk命令

# 只打印1

技术分享图片

# 不会打印$0

技术分享图片

4.7next

next的作用是跳过当前行。直接从下一行 开始处理

# 跳过第2行

技术分享图片

 

5awk数组

5.1、基础概念

1awk中的数组是一个使用字符串作为下标的“关联数组”。

2)我们在使用时,可以用 数字/字符串 作为下标,不过使用数字作为下标时,awk默认会把“数字”下标转换为“字符串”。

3)在awk中,元素的值可以设置为“空”。

4当一个元素不存在于数组时,如果我们直接引用这个不存在的元素,awk会自动创建这个元素,并且默认为这个元素赋值为“空字符串”

5)在awk中,判断数组中元素是否存在,用“if(下标 in 数组名)”。即判断数组中是否有key

6)使用split函数生成的数组,下标默认是从1开始的

5.2、基本操作

# 创建数组,直接创建就可以

技术分享图片

# 删除数组中的元素

awk ‘BEGIN{ …;delete huluwa[0]}’

# 删除整个数组

awk ‘BEGIN{ …;delete huluwa}’

# for循环有序遍历数组。只有下标是数字时,通过下标的递增,才能有序遍历

awk ‘BEGIN{ …;for (i=1;i<=3;i++){print i,huluwa[i];} }’

# for循环无序遍历数组。因为awk数组本身是无序的关联数组

awk ‘BEGIN{ …;for (i in huluwa){print i,huluwa[i]} }’

# 实例应用——统计某文件$1 重复出现的次数

awk ‘{count[$1]++} END{ for (i in count ) {print i,count[i]} }’ file

 

# 实例应用——统计某文本人名出现次数

awk ‘{ for (i=1;i<=NF;i++) {count[$i]++} } END{ for (a in count) {print a,count[a]} }

 

6awk内置函数

6.1、算术函数

rand函数,srand函数,int函数

rand函数固定打印了0.237788srand函数固定打印1,两者合用,可生成小于1的随机数

# rand函数

awk 'BEGIN{print rand()}'

0.237788

# srand函数

awk 'BEGIN{print srand()}'

1

# 生成小于1的随机数

awk 'BEGIN{srand();print rand()}'         

0.319498

# 通过随机数乘100,在通过int函数取整,生成0~100间的随机数

awk 'BEGIN{srand();print int(100*rand())}'

76

 

6.2、字符串函数

gsub函数,sub函数

这两个函数用于替换某些 文本

awk ‘{ gsub (“old”,“new”,$1);print $0}’file

awk ‘{ gsub (“[a-z]”,“new”,$1);print $0}’file

gsub将指定范围内匹配的字符全部替换为新字符

sub用法与gsub一样,但只替换匹配范围内第一次匹配到的字符

# 比如某文件就一行,$1=aaa。

gsub(“a”,“b”),则$1=bbb。第三个参数不加,则默认为$0

sub(“a”,“b”),则$1=baa。

length函数

length函数可获取指定字符串的长度。不指定参数,默认为$0

awk ‘{ for (i=1;i<=NF;i++) {print $i,length($i)} }’file

index函数

获取指定字符串位于整个字符串中的位置

awk ‘{print index($0,“LEE”)}’file

0

7

0

index函数在每一行中查找LEE,如果该行没有,返回0,该行有,返回位置

split函数

split函数可以切割字符串,帮我们动态生成数组。生成的数组下标从1开始

# 将ts以“;”分隔,并将分隔后的str保存到huluwa数组中

awk –v ts=”one;two;three”‘BEGIN{ print split(ts,huluwa,”;”)}’

# split函数的返回值就是数组长度

split(ts,huluwa,”;”) == 3

6.3、排序函数

asort函数

asort函数根据数组的value值进行排序

# asort排序后,原有key将被数字替代

awk 'BEGIN{ t["a"]=66;t["b"]=88;t["c"]=35 ; asort(t) ; for (i in t){print i,t[i]} }'

1 35

2 66

3 88

# asort排序时,新建一个数组。t[]不变,新创了new[]

awk 'BEGIN{ t["a"]=66;t["b"]=88;t["c"]=35 ; asort(t,new) ;

for (i in new){print i,new[i]} }'

# asort函数的返回值就是数组的长度

asort(t,new)==3

asorti函数

asorti函数会对原数组的key排序,然后将key作为value生成一个新数组

awk 'BEGIN{ t["a"]=66;t["b"]=88;t["c"]=35;asorti(t,new);for (i in new){print i,new[i]} }' 

1 a

2 b

3 c

# 通过asorti排列原数组

awk 'BEGIN{ t["a"]=66;t["b"]=88;t["c"]=35;asorti(t,new);

for (i in new){print i,new[i],t[new[i]] } }'

1 a 66

2 b 88

3 c 35

 

 

7、三元运算与打印奇偶行

7.1、三元运算

# if…else判断用户类型

awk –F : ‘{ if($3<500){usertype=“系统用户”}else{ usertype=“普通用户”};

print $1,usertype }’/etc/passwd

# 三元运算符替换if…else

awk –F : ‘{ usertype=$3<500?“系统用户”: “普通用户”

print $1,usertype }’/etc/passwd

l  $3<500:条件判断

l  ?”系统用户”:为真,则“系统用户”赋给usertype

l  :“普通用户”:为假,则“普通用户”赋给usertype

# 三元运算符统计“系统用户”和“普通用户”数量

awk -F: '{$3<500?a++:b++}END{print a,b}' /etc/passwd

7.2、打印奇偶行

# 打印奇数行

awk ‘a=!a’flie

# 打印偶数行

awk ‘!(a=!a)’flie

解析:

我们知道awk的正则匹配是

技术分享图片/

但如果我们不加print动作,仅仅有正则,那么会默认打印$0

awk ‘/正则/’file

而在awk中,非0/非空str表示“真”。0/空表示“假”

# 注意,这不是正则,‘2’不为0/空,打印file所有

awk '2' file

所以’a=!a’

1) a没有定义,初始化a=‘’,a为“假”

2) !a为“真”

3) a=!a,a变为“真”,打印第1行

4) !a又变为“假”,不打印第2行

 

 

‘!(a=!a)’

1)a=!a为真,!(a=!a)为假,不打印 第1行

2)a=!a为假,!(a=!a)为真,打印第2行

8、参考文档

awk从放弃到入门 (http://www.zsythink.net/?s=awk)

awk用法(使用入门) (https://www.cnblogs.com/emanlee/p/3327576.html)

官方文档 (https://www.gnu.org/software/gawk/manual/html_node/index.html#SEC_Contents)

 

sed

sed命令是一个面向字符流的非交互式编辑器,按行来处理文本内容。在shell中,使用sed来批量修改文本内容是非常方便的。

 

1sed的工作原理

sed 把每一行都存在临时缓存区中,对这个副本进行编辑,所以不会修改或破坏源文件。具体过程如下:

1)sed 把当前正在处理的行保存在一个临时缓存区中,这个缓存区称为“模式空间”或“临时缓冲”。

2)sed 对模式空间中的行后处理完毕后,就把该行发送到屏幕上(除非之前有命令删除这一行或取消打印操作)。

3)sed处理完输入文件的最后一行后, sed 便结束运行。

技术分享图片

2sed命令详解

2.1sed命令的语法格式

sed的命令格式

sed [option] 'sed command'filename

sed的脚本格式

sed [option] -f 'sed script'filename

2.2sed命令的选项(option)

-n :使用安静(silent)模式。在一般 sed 的用法中,所有来自 STDIN 的数据一般都会被列出到终端上。但如果加上 -n 参数后,则只有经过sed 特殊处理的那一行(或者动作)才会被列出来。

-e :多重编辑,且命令顺序会影响结果

-f :直接将 sed 的动作写在一个文件内, -f filename 则可以运行 filename 内的 sed 动作;

-r :sed 的动作支持的是延伸型正规表示法的语法。(默认是基础正规表示法语法)

-i :直接修改读取的文件内容,而不是输出到终端。

2.3sed定位文本的方式

x

x为行号

x,y

表示行号从x到y

/pattern

查询包含模式的行

/pattern /pattern

查询包含两个模式的行

pattern/,x

在给定行号上查询包含模式的行

x,/pattern/

通过行号和模式查询匹配的行

x,y!

查询不包含指定行号x和y的行

2.4sed操作命令(command

命 令

说 明

a

在当前行后添加一行或多行。

sed ‘/pattern/a new_str’file;sed ‘1a new_str‘ file

c

用新文本修改(替换)当前行中的文本

d

删除行

i

在当前行之前插入文本

h

把模式空间里的内容复制到暂存缓存区

H

把模式空间里的内容追加到暂存缓存区

g

取出暂存缓冲区里的内容,将其复制到模式空间,覆盖该处原有内容

G

取出暂存缓冲区里的内容,将其复制到模式空间,追加在原有内容后面

l

列出非打印字符

p

打印匹配行(和-n选项一起合用)

=

显示文件行号

{}

定位执行的命令组,“;”隔开

n

读入下一输入行,并从下一条命令而不是第一条命令开始处理

q

结束或退出 sed

r filename

从另一个文件中读文本,类似输入重定向   <

对所选行意外的所有行应用命令

s

用一个字符串替换另一个

2.5、替换标志

g

在行内进行全局替换

p

打印行

w filename

写文本到一个文件,类似输出重定向   >

x

交换暂存缓冲区与模式空间的内容

y

传送字符,替换单个字符(不能对正则表达式使用 y 命令)

2.6sed的正则表达式

元字符

功 能

示 例

示例的匹配对象

^

行首定位符

/^love/

匹配所有以 love 开头的行

$

行尾定位符

/love$/

匹配所有以 love 结尾的行

.

匹配除换行外的单
  个字符

/l..e/

匹配包含字符 l、后跟两个任意
  字符、再跟字母 e 的行

*

匹配零个或多个前
  导字符

/*love/

匹配在零个或多个空格紧跟着
  模式 love 的行

[]

匹配指定字符组内
  任一字符

/[Ll]ove/

匹配包含 love 和 Love 的行

[^]

匹配不在指定字符
  组内任一字符

/[^A-KM-Z]ove/

匹配包含 ove,但 ove 之前的那
  个字符不在 A 至 K 或 M 至 Z 间
  的行

(..)

保存已匹配的字符



&

保存查找串以便在
  替换串中引用

s/love/**&**/

符号&代表查找串。字符串 love
  将替换前后各加了两个**的引
  用,即 love 变成**love**

<

词首定位符

/<love/

匹配包含以 love 开头的单词的
  行

>

词尾定位符

/love>/

匹配包含以 love 结尾的单词的
  行

x{m}

连续 m 个 x

/o{5}/

分别匹配出现连续 5 个字母 o、
  至少 5 个连续的 o、或 5~10 个
  连续的 o 的行

x{m,}

至少 m 个 x

/o{5,}/


x{m,n}

至少 m 个 x,但不
  超过 n 个 x

/o{5,10}/


 

2.7、字符集

[:digit:]

所有数字,即[0-9]

[:lower:]

所有的小写字母

[:upper:]

所有的大写字母

[:alpha:]

所有的字母

[:alnum:]

相当于0-9a-zA-Z

[:space:]

空白字符

[:punct:]

所有标点符号

 

2.8sed实例

# {}的应用

sed -n '1,4{=;p}' passwd

# a的应用

sed ‘/pattern/a new_str’file # 在匹配模式的下一行新,增str

sed ‘1a new_str‘ file # 在第1行后,新增str

# !的应用

# 过滤#注释行和空格行

sed –n ‘/^#/!{/^$/!p}’file

l  /^#/!:打印除了#开头的行

l  {/^$/!p}:打印除了空格行

# -e 的应用

# 删除#注释行和空行。有时-e的不同顺序,会造成不同结果。比如 -e ’1a’–e ‘2a’

sed –e ‘/^#/d’-e ‘/^$/d’ file

# 将hello所在行的END替换为tail

sed –i ‘/hello/[email protected]@[email protected]#’

l  @:地址定界符,还可以是/,#等其他特殊字符

# ()&

# 将目录下的.txt文件批量命名为.sh文件

find . –name ‘*.txt’ | sed –re ‘s#(.*).txt#mv & 1.sh#e’

l  (.*).txt:查找的文件,对应&

l  (.*):分组,对应1,多个括号就依次对应2,3,…

l  e:执行mv命令

# <>

# 删除文件中含有you这个单词的行。必须加

sed ‘/<you>/d’file

3、参考文档

linux sed命令详解(推荐) (http://www.jb51.net/article/111306.htm)

linux命令总结sed命令详解 (https://www.cnblogs.com/ginvip/p/6376049.html)

sed命令详解 (https://www.cnblogs.com/ctaixw/p/5860221.html)

 

grep

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

1、grep的参数

--color=atuo或者—color:对匹配到的文本着色

-i:忽略大小写

-n:显示结果所在行号

-c:统计匹配到的行数。注意:是匹配到的总行数,不是匹配到的次数

-o:只显示符合条件的字符串,但是不整行显示。每个符合条件的字符串单独显示一行

-v:接啥排除啥

-w:匹配整个单词,如果是字符创中包含这个单词,则不会匹配

-Ax:输出的时候包含结果所在行之后的指定行数,x是行数,A:after。如果有多个匹配结果。则每个结果的后x行都会显示

-Bx:输出的时候包含结果所在行之前的指定行数,x是行数,B:before。

-Cx:输出的时候包含结果所在行之前和行之后的指定行数,x是行数,C:context

-e:实现多个选项的匹配,逻辑or关系

-q:静默模式,不输出任何信息。于“echo $?”合用,查看是否匹配到,0表示匹配到,1表示没有匹配到

-P:使用兼容的perl的正则

-E:使用扩展正则表达式,同egrep

# -e的使用

grep –e’one’ –e’two’ file # 可以同时匹配one和two

练习题

 

1、将/etc/passwd 文件的前10行输入到passwd中,将passwd变为只有单词/字母存在的文本

sed -nr 's#[:/0-9]+# #gp' passwd.txt  #对passwd.txt文件进行处理,将 FS 变为空格

2、将/etc/passwd 文件的前10行输入到passwd中,计算文件中每个单词的重复数量

sed -nr 's#[:/0-9]+# #gp' passwd.txt | sed -nr 's# # #gp' | sort | uniq -c | sort –nr

l  sed -nr 's#[:/0-9]+# #gp' passwd.txt  #对passwd.txt文件进行处理,将 FS 变为空格

awk 'BEGIN{RS="[:/0-9]+"}{print $0}' passwd.txt | head -n -1 | sort | uniq -c | sort -nr  # head -n -1 是因为最后一行是空行,需要排除

3、从处理过的passwd文件中,找出第一列有12o的行,并打印行号

# awk使用{m,n},需要加--posix

awk --posix ‘$1~/o{1,2}/{print NR,$1}’passwd

4、统计某一文件里空行的数量

sed -nr 's#^$##gp' file | wc -l

grep "^$" file |wc -l 

awk '/^$/{a=a+1} END{print a}' file

5、以 : 为分隔符,统计/etc/passwd文件中$3>5的行数

awk -F: '{$3>5?a++:b++} END{print a}' /etc/passwd

awk -F: '$3>5{a++;print NR,$0} END{print a}' /etc/passwd

6、找出环境变量$PATH中,所有只有三个任意字符的命令,如tee,并将它们重定向到command.txt中。每行显示1一个,并统计总个数

find $(echo $PATH | tr ":" " ") -type f -name "???" 1> command 2>/dev/null;wc -l command

7、处理以下文件内容,将域名取出,并根据域名进行技术排序处理(去重)

http://www.cbl.org/index.html

http://www.cbl.org/1.html

http://post.cbl.org/index.html

http://mp3.cbl.org/index.html

http://www.cbl.org/3.html

http://post.cbl.org/2.html

awk -F "/" '{a[$3]++} END{for(i in a){print i,a[i]}}' test

8处理以下文件内容,去重

111 222 333 444 222 222 111 111 11 11

22 33 44 55 33 33 55 22

77 88 77 77 88 99 33 33

awk '{for(i=1;i<=NF;i++)a[$i,NR]++}

{for (j in a) {split(j,m,SUBSEP);if(m[2]==NR)printf m[1]" "} printf " "}' test

l  a[$i,NR]:二维数组

l  for (j in a):遍历,j是二维数组

l  split(j,m,SUBSEP):切割二维数组,SUBSEP是切割二维数组的分隔符

l  printf m[1]:如果使用print,则每个m[1],都会自动换行。printf不会,print需要自定义格式

l  printf " ":换行。awk是一行一行处理的,一行处理完,换行,美化输出


以上是关于Linux三剑客的主要内容,如果未能解决你的问题,请参考以下文章

Linux入门开发: 学习linux三剑客(awksedgrep)(上)

Linux三剑客之grepegrep及正则表达式使用详解

Linux三剑客

Linux三剑客

Linux三剑客AwkSedGrep 命令详解

linux三剑客之sed史上最实用教程!