linux三剑客详解

grep命令

⽀持的正则参数

支持的正则 描述
-E,--extended-regexp 模式是扩展正则表达式(ERE)
-P,--perl-regexp 模式是perl正则表达式
-e,--regexp=PATTERN 使用模式匹配,可指定多个模式匹配
-f,--file=FILE 从文件每一行获取匹配模式
-i,--ignore-case 忽略大小写
-l,--files-with-matches 只匹配列出行所在的文件名
-w,--word-regexp 模式匹配整个单词(精确匹配)
-x,--line-regexp 模式匹配整行,精确匹配
-v,--invert-match 打印不匹配的行(取反)

输出控制参数

输出控制 描述
-c,--count 只打印每个文件匹配的行数
-h,--no-filename 不输出文件名
-H,--with-filename 打印每个匹配的文件名
-m,--max-count=NUM 输出匹配的结果num数
-n,--line-number 打印行号
-o,--only-matching 只打印匹配的内容
-q,--quiet 不输出正常信息
-r,--recursive 递归目录
-s, --no-messages 不输出错误信息
--include=FILE_PATTERN 只检索匹配的文件
--exclude=FILE_PATTERN 跳过匹配的文件
--exclude-from=FILE 跳过匹配的文件,来自文件模式
--exclude-dir=PATTERN 跳过匹配的目录

内容行控制参数

内容行控制 描述
-A,--after-context=NUM 打印匹配的后几行
-B,--before-context=NUM 打印匹配的前几行
-C,--context=NUM 打印匹配的前后几行
--color[=WHEN], 匹配的字体颜色

sed命令

选项参数

参数 描述
-n 不打印模式空间 取消默认sed的输出,常与sed内置命令的-p连用 输出想要的内容
-e 执行脚本,表达式来处理
-f 执行动作从文件读取执行
-i 修改原文件 直接修改文件内容,而不是输出到终端
-r 使用扩展正则表达式和正则表达式
-i.bak 在将处理的结果写入文件之前备份一份

内置参数

常用的:

-p 全拼print,表示打印匹配行的内容,通常p会与选项-n一起使用※
-d delete 删除的意思
= 显示行号
s 替换 通常和g一起
g 全局替换
a 追加,添加 当前行追加文本
i 当前插入 当前行上面插入文本

全部:

命令 描述
s /regexp/replac ement/ 替换字符串 加上g 全局替换
a \text 当前行追加文本
i \text 当前行上面插入文本
c \text 所选行替换新文本
b label 分支到脚本中带有标签的位置,如果分支不存在则分支到脚本的末尾
d 删除模式空间,开始下⼀个循环
D 删除模式空间的第⼀⾏,开始下⼀个循环
g G 复制/追加保持空间到模式空间
h H 复制/追加模式空间到保持空间
I 打印模式空间的⾏,并显示控制字符$
n N 读取/追加下⼀⾏输⼊到模式空间
p 打印当前模式空间
P 打印模式空间的第⼀⾏
q ⽴即退出 sed 脚本
r 追加⽂本来⾃⽂件
t label 如果 s///是⼀个成功的替换,才跳转到标签
w filename 写⼊当前模式空间到⽂件
x 交换模式空间和保持空间内容
= 打印当前⾏号
: label label 为 b 和 t 命令
! 取反、否定
& 引⽤已匹配字符串

地址参数

地址 描述
first~step 步⻓,每 step ⾏,从第 first 开始
$ 匹配最后⼀⾏
/regexp/ 正则表达式匹配行
number 只匹配指定⾏
addr1,addr2 开始匹配 addr1 ⾏开始,直接 addr2 ⾏结束
addr1,+N 从 addr1 ⾏开始,向后的 N ⾏
addr1,~N 从addr1行开始,到N行结束

awk

awk常用参数

参数 含义
-F 指定分隔符
-v 指定变量和默认值
$NF 代表最后一个字段
NR 代表第几行
&&
$ (NF- (n-1)) 取倒数第n列
FS 输入分隔符,与-F分隔符一样
OFS 输出字段分隔符
RS 输入记录分隔符
$0 显示整行
1...N 第一个字段到第N个字段

awk参数具体玩法

-F 指定分隔符

复制代码
# 指定分隔符":",并截取第六个字段
tail -1 /etc/passwd | awk -F ":" '{print $6}'

# 指定两个记录分隔符(空格和:)
awk -F'[ :]' '{print $2,$4}' 

# 多一个加号表明将连续出现的记录分隔符当做一个来处理
awk -F'[ :]+' '{print $2,$4}'

# 在awk中,当记录分隔符指定为空字符串时,awk会将多个连续的空白看做一个单一的记录分隔符。此外,awk还会忽略开头和结尾处的空白。

-v 指定变量和默认值

复制代码
# 生成一个1到10的文件,我想计算出文件内的总和
seq 1 10 > 1.txt 

# 给a赋值为0,让a与文件内的第一个字段相加,最后结果通过tail 打印出来 但是看的出来很麻烦
awk -v "a=0" '{a+=$1;print a}' 1.txt | tail -1

# 优先级END方式 下面会有讲
awk -v "a=0" '{a+=$1}END{print a}' 1.txt

$NF代表最后一个字段

复制代码
awk -F ":" 'NR==10{print $NF}' /etc/passwd 
# 截取/etc/passwd文件下面的第10行,最后一个字段

NR 选行

复制代码
awk NR==44'{print $0}' /etc/passwd 
# 打印/etc/passwd下的第44行,$0代表整行

&&与

条件1 && 条件2 都要满足才为真,真返回1,假返回0

复制代码
# 如果条件为假则返回0
awk -v "a=0" 'NR==1{print (a+=$1 > 10) && (a+=$2 >10)}' 2.txt 

# 如果为真返回 1
awk -v "a=0" 'NR==1{print (a+=$1 < 10) && (a+=$2 <10)}' 2.txt

||或

条件1 || 条件2 ,条件满足一边 为真

复制代码
# 两个条件都不满足,返回假,也就是0
awk -v 'a=0' 'NR==1{print (a+=$1 >10) || (a+=$2 < 10)}' 2.txt

# 第二行,两边条件满足一遍,所以结果为1
awk -v 'a=0' 'NR==2{print (a+=$1 >10) || (a+=$2 < 10)}' 2.txt

FS指定分隔符

复制代码
# 没有优先级写法
awk '{FS=":"}NR==2{print $1,$2}' 3.txt

# 优先级写法
awk 'BEGIN{FS=":"}NR==2{print $1,$2}' 1.txt

OFS一般与FS或者-F共同使用

复制代码
#指定分隔符":",OFS中间的间隔换成你指定的
awk -F ":" 'NR==2{OFS="_";print $1,$2}' 1.txt  

#FS用法与上面意思相同
awk 'BEGIN{FS=":";OFS="-"}NR==2{print $1,$2,$3}' 1.txt

RS指定结尾符一般与OFS配合

写法单独写RS:

复制代码
# 在文本操作的时候结尾默认是回车(\n),RS指定结尾符号
awk 'BEGIN{RS=""}{print $0}' 2.txt

RS与OFS配合使用写法:

注意 如果是$0的话,不会有效果,单独使用是可以,如果配合OFS使用就不能是整行

复制代码
# RS指定结尾符,OFS指定链接符
awk 'BEGIN{RS="";OFS="##"}{print $1,$2,$3}' 2.txt

# 也可以指定特殊符号
awk 'BEGIN{RS="";OFS="\n"}{print $1,$2,$3}' 2.txt

awk优先级

最高:BEGIN是最高优先级,是在执行PROGRAM之前执行的,不需要提供数据源,因为不涉及任何数据,也不依赖PROGRAM代码块;

默认:PROGRAM是对数据流干什么,是必选代码块,也是默认代码块。所以执行的时候必须要加上数据源; 默认优先级(不加优先级就是默认)

最低:END是处理完数据流后,如果需要执行END代码块,就必须要PROGAM的支持,单个无法执行

注意:如果只用最高或者最低优先级,后面跟上数据源(file)不会有效果,只有默认优先级PROGRAM才会有效果

最高优先级 BEGIN

写法一:

复制代码
# BEGIN后面不需要加任何数据源,也可以打印内容
awk 'BEGIN{print "zhangsan"}'

写法二(赋值写法):

复制代码
# 将a[1],a[2]赋值,并打印
awk 'BEGIN{a[1]="zhangsan";a[2]="28";print a[1],a[2]}'

# 与上面同理
awk 'BEGIN{name="zhangsan";age="28";print name,age}'

默认优先级PROGRAM(对数据源操作)

复制代码
# 比如我想计算机内存使用率(总内存 - 空闲 *100 / 总内存)
# 将总内存赋值给a,空闲内存赋予b ,在利用算法算出内存使用率
awk 'NR==1{a=$2}NR==2{b=$2;print(a-b)*100/a"%"}' /proc/meminfo

END最低优先级

对数据处理的最后一个值

复制代码
# 生成一个1到10 的文件
seq 1 10  > 1.txt

# $1代表第一个字段,将第一个字段的所有数相加
awk -v "a=0" '{a+=$1}END{print a}' 1.txt

我们把第一个字段加起来了,会发现很多数值,我们就要最后一个结果,我们就加上END看两者的区别

awk模糊匹配

比如说我想看我的用户信息,我就记得用户是gx开头的,我不打开文件下,我们可以这么做:

复制代码
awk -F ":" '$1 ~ "gx"{print $0}' /etc/passwd
# 注意"~"匹配查询,后面关键字要用引号引起来一定要双引号 
# $1代表第一个字段,可以写成别字段比如第二字段就是$2...

# 匹配多个写法
awk -F ":" '$1 ~"gx"{print $0};$1 ~ "roo"{print $0}' /etc/passwd

awk命令控制流

if判断语句

复制代码
# 双分支
awk '{
    if (条件) {
        # 条件成立时执行
        动作1
    } else {
        # 条件不成立时执行
        动作2
    }
}' 文件名

# 多分支
awk '{
    if (条件) {
        动作1
    } else {
        动作2
    }
}' 文件名

# 如果$1大于5,$1乘以$2,否则$1除以$2
awk '{
    if ($1 > 5) {
        print $1 * $2
    } else {
        print $1 / $2
    }
}' 2.txt

for循环

复制代码
# 初始化值a,然后内容有几行循环就几次,最后将字段相加,就是结果了
awk '{a=0;for(i=1;i<11;i++){a+=$i}print a}' 2.txt

while循环

复制代码
# 单条语句写法
awk '{a=0;b=1;while(b<10){a+=$b;b++}print a}' 2.txt

# 逐行写法
awk '{
    sum = 0
    i = 1
    while (i < 11) {
        sum += $i
        i++
    }
    print sum
}' 2.txt

do...while写法

复制代码
# do...while 就是将写在while中的语句拿出来写,最后while循环
awk '{a=0;b=1;do{a+=$b;b++}while (b<11)print a}' 2.txt

# 多行写法
awk '{
    a = 0
    b = 1
    do {
        a += $b
        b++
    } while (b < 11)
    print a
}' 2.txt

awk数组

语法

复制代码
array_name[index]=value

array_name:数组的名称
index:数组索引
value:数组中元素所赋予的值

访问数组元素

复制代码
# 访问数组中某个值
arrayname[index]

# 访问数组中所有的元素
for(idx in arrayname){print arr[idx]}

删除数组元素

复制代码
# 删除数组中特定下标的元素
delete arrayname[index]

# 删除数组中所有的元素
for (idx in arrayname){delete arrayname[idx]}

数组案例

这个文件包括了网关服务器所需要的ip地址列表,文件中的数据符合下面的格式:

复制代码
cat Iplogs.txt
180607 093423    123.12.23.122 133
180607 121234    125.25.45.221 153
190607 084849   202.178.23.4 44
190607 084859   164.78.22.64 12
200607 012312    202.188.3.2 13
210607 084849   202.178.23.4 34
210607 121435    202.178.23.4 32
210607 132423    202.188.3.2 167

列出所有的IP地址和它被请求的次数:

复制代码
awk '{Ip[$3]++} END {for (var in Ip) print var, "accessed", Ip[var], "times"}' Iplogs.txt
123.12.23.122 accessed 1 times
164.78.22.64 accessed 1 times
202.188.3.2 accessed 2 times
125.25.45.221 accessed 1 times
202.178.23.4 accessed 3 times

# Ip[$3]++ 表示每次遇到一个 IP 地址时,其计数加 1
# 遍历 Ip 数组中的每个元素。输出每个 IP 地址及其访问次数。