• grep、awk、sed,三剑客介绍


    三剑客

    grep sed awk
    -----------------------------------------------------------------------------------------------------------------------------------------
    grep :行级过滤器、过滤文本中指定的内容(行)

    使用格式:
    grep [OPTIONS] PATTERN [FILE...]

    options: 选项
    pattern: 模式匹配
    file: 文件名
    注意: 将文件内容逐行读入到内存,进行模式匹配,一旦匹配成功,则显示该行一整行内容;如果没有匹配成功,则该行从内存中退出

    一·常用选项

    1). -i : 忽略大小写
    2). -v : 取反
    3). -A : 向后多显示几行
    4). -B : 向上多显示几行
    5). -C : 上下各多显示几行
    6). -n : 显示过滤出内容,在原文件中的行号
    7). -q : 静默输出,不会显示过滤内容;不会影响状态结果
    8). -c : 统计过滤出了多少行
    9). -rl : 根据文件中内容,过滤文件路径
    10). -R : 根据文件中内容,过滤文件路径(会显示过滤的文件内容所在的行)

    二·grep命令执行的状态结果:

    可以过滤出内容: $? 为 0
    没有过滤到内容: $? 为 1
    文件名不存在: $? 为 2

    ------------------------------------正则表达式-----------------------------------------

    正则表达式: 利用特殊字符,去代表特定的含义

    元字符:

    . 代表任意单个字符

    * 代表了前面一个字符,可以出现0次到n次
    例: ab*c --> ac abc abbbc abbbbbc

    .* .可以出现0次到n次,也就代表了任意多个字符
    注意:.*在匹配时,处于贪婪模式;能更多匹配,则去进行更多匹配

    [] 从括号中任选一个字符

    [^] 括号中的^代表取反

    ^ 行首锚定、行首

    $ 行尾锚定、行尾

    ^$ 空行

    < 词首锚定、词首

    > 词尾锚定、词尾

    转义符,将特殊含义去除

    {} 引用、跟*类似; {5}前面字符必须出现5次;{2,5} 前面字符可以出现2次-5次

    ? 代表了前面一个字符,可以出现0次或1次

    + 代表了前面一个字符,可以出现1次到n次

    () 分组;1 2 做分组后项引用

    1 引用前面定义的第一个分组
    2 引用第二个分组

    1 2 3
    (www) (.baidu.) (com)

    ((www).baidu.) (com) 1 --> www.baidu. 2 --> .baidu. 3 --> com

    [a-z]{3} 匹配三个连续的字符

    ([a-z])11 匹配三个相同的连续字符
    @@@-------awk功能:awk -F "." '{print $3"."$2"."$1}' 文件名 > 目标文件

    vim替换功能:

    定界(定址) s/旧内容/新内容/修饰符

    逐行操作,读取一行,先做定界,如果定界成功,则执行替换

    例1:
    %s/o/H/

    %代表了定界,代表所有行
    3s : 只替换第3行;只在第3行执行s替换动作
    1,3s : 替换1到3行;在1到3行执行s替换动作

    注意: 默认只替换每行第一次匹配成功的字符

    %s/o/H/g g是修改符,代表全局替换

    注意:在vim替换功能中,旧内容匹配,支持正则表达式

    --------------------------------------- sed 流编辑器 ----------------------------------------------------

    工作原理
    将文件逐行读入到内存;先定界(定址);定界成功,则运行子命令;若没定界成功,则不运行子命令;无论是否定界成功,只要没有执行具有删除动作的子命令,则默认将该行打印
    sed一般用于处理大文件。
    语法:
    sed [选项] “定界 子命令” 文件名

    ----------------------模式空间

    1、常用的选项
    -n:静默输出,关闭模式空间的输出,一般与p一起用
    -e:允许进行多项编辑,也就是说对同一行做多次处理、也可以做多点编辑
    -e '动作' -e '动作' 等价于 '动作1;动作2'
    -f sed脚本 : 指定运行的sed脚本的
    -r:允许使用扩展正则
    -i:直接修改原文件
    2、定界方式:

    ----单个数值定界:
    sed '9p' pass.txt
    9代表定界到第九行

    ----两个数值:
    sed '1,4 p' pass.txt

    定界1到4行

    sed '$ p' pass.txt
    sed '3,$ p' pass.txt

    $代表最后一行

    ----单个正则表达式:

    sed '{/正则表达式/ 子命令 }' 文件名

    sed '{/^bin/ p }' pass.txt

    ----两个正则表达式:
    sed '{/正则表达式1/,/正则表达式2/ 子命令 }' 文件名

    表达式1代表起点:

    表达式2代表终点:

    *****注释: 第一次匹配到表达式1算作起点;第一次匹配到表达式2算作终点
    如果能匹配到表达式1,但是无法匹配到表达式2,则从匹配到表达式1的行开始,一直到文件末尾,都算定界成功
    如果表达式1没有匹配成功,则所有行都定界失败

    续行: 3,+4
    sed '{3,+4 p }' pass.txt

    步长: 1~2

    sed '1~2 p' pass.txt

    定界后,可以跟多个子命令:

    3{p;p;p} 定界到3行时,执行3次p的子命令
    3p;5p 定界3行和5行,分别运行子命令

    3、Command

    常用的:d p s y q
    其他的:a c i r w
    h H g G 用于模式空间和保留空间之间的操作
    1)d:删除
    ~# sed '5,$d' /etc/passwd 删除从第5行开始到最后一行的所有内容

    2)p:打印
    ~# sed -n '3,5p' pass // 打印文件的3到5行

    3)r 读取,读取外部一个文件
    ~# sed '/^root/r /etc/issue' /etc/passwd

    4)w 写,会将匹配到的内容,保存到外部的一个文件中
    ~# sed '/root/w /tmp/douni' pass //将匹配到的行另存到文件中

    5)a 追加 在匹配到的行的下一行插入内容
    ~# sed '/root/a hello root' pass

    6)i 插入 在匹配行的上一行插入内容
    ~# sed '/daemon/i SO COOL' pass

    7)c 修改 本行替换,将匹配到的行的内容替换成新内容
    ~# sed '/root/c ROOT' pass

    8)y 转换的命令,对应替换(替换字符相等长度)
    ~# sed 'y/1234/ABCF/' pass

    9)n next 处理匹配行的下一行,用的较少
    ~# sed -n '/root/p' pass

    10)q 退出 不再向模式空间读入新行
    ~# sed '/^bin/q' /etc/passwd

    11)s 查找替换
    定址s/模式匹配(旧的内容)/新的内容/[修饰符]


    ----------------------------------- 保留空间

    h:将模式空间的内容复制到保留空间 —— 覆盖模式
    H:将模式空间的内容追加到保留空间 —— 追加模式
    g:将保留空间的内容复制到模式空间 —— 覆盖模式
    G:将保留空间的内容追加到模式空间 —— 追加模式

    x:将模式空间的内容和保留空间的内容进行交换

    交换第一行和第二行的内容
    ~# sed '1{h;d};2G' pass

    公式:#sed '1{h;d};2{G;h;d};3G' pass

    #sed '1{h;d};2,4{G;h;d};5G' a.txt


    ------------------------------------------ AWK ----------------------------------------------
    功能:对文本数据进行汇总和处理,是一个报告的生成器,能够对数据进行排版;格式化输出

    AWK工作过程:
    将文件内容逐行读入到内存;根据输入分隔符自动切片;将每片内容赋给指定的变量;定界(定界条件);一旦定界成功,则运行处理动作;一旦定界失败,不运行处理动作。

    默认输入输出分隔符:空白;多个连续的空白当做一个分隔符

    #vim a.txt
    hello from tom $0:一整行
    $1 $2 $3
    用法格式------------------------------------------------------------------------------------------------

    语法 : awk 选项 ‘定界 {处理动作1,处理动作2...}’ 文件名[文件2...]

    基本内容:

    -----awk输出
    (1)print --打印内容的,内容可以是文件中的内容,也可以跟文件内容毫无关系
    :换行符(默认) : 制表符
    例: #echo hello | awk '{print "welcome to our school"}' ------echo作用相当于提供一个行;print$0
    #welcome to our school

    例: #echo hello | awk '{print "welcome to our school"}'
    #welcome to
    #our school

    (2)printf —— 可以格式化输出的,默认没有换行
    %s:表示是字符串
    %d:表示十进制数 (%d直接取整,不进行四舍五入)
    %f: 表示浮点数,其实就是小数 float (%f进行四舍五入的)
    %%:表示%本身;可以不传递值
    %x:表示十六进制数
    %o:表示八进制数
    %c:表示字符

    修饰符: N(数字) 表示显示宽度 %10s
    - 表示左对齐,默认是右对齐 %-10s
    %% 表示% %d %% -----> 99 %

    对于浮点数: %5.2f : 其中5表示总的显示宽度(整数位+小数位),2表示小数位的位数

    #awk -F ":" '{printf "hello %s and uid %d ",$1,$3}' pass.txt
    #hello root and uid 0


    ------选项

    -F:指定输入文件字段分隔符

    例: 打印pass文件中的用户名和uid

    # awk -F “:” '{print $1,$3}' pass
    # awk -F “:” '{print $1"用户uid为"$3}' pass --指定输出分隔符(方式一)
    laozhang 用户uid为 500

    ----同时指定多个分隔符(:和/都是分隔符)

    # awk -F"[:/]" '{print $1,$10}' pass

    -v:调用指定变量并赋值 (大多用在脚本中)

    -v FS=":" 指定输入分隔符
    #awk -v FS=":" '{print $1,$3}' pass.txt

    -v OFS="-->" 指定输出分隔符

    -v RS="," 指定行分隔符(以谁分隔行)

    -v NF:当前行的字段数
    打印文件每一行最后一个字段
    #awk '{print $NF}' a.txt

    ---------扩展:awk脚本 文件内容为awk命令的 '' 里的内容
    vim a.sh
    #!/bin/awk -f
    BEGIN {
    FS=":"
    }
    $2~/tom/{
    print "nihao"
    }

    ------awk的变量

    种类:内置变量、自定义的变量
    1)内置变量(內建变量)
    (1) $0 $1 $2 $3 ...
    (2) 与记录相关的变量(记录就是行)
    FS(field separator):输入字段分隔符,默认是空白
    FS=":"
    OFS(Output):输出字段分隔符
    RS(record):记录的分隔符,即行的分隔符,输入行分隔
    注意:在输入时,指定完分隔符后, 失效
    ORS:输出记录分隔符
    #awk -v FS=':' '{print $1}' /etc/passwd
    (3)与数据相关的变量
    NR(Number of Record):记录数,awk的处理的行的总数 NR在很多情况下可以看成行号
    读第一行时,NR等于1
    读第二行时,NR等于2
    读第三行时,NR等于3
    ...

    FNR:行号,不会叠加
    NF(Number of Field):当前行的字段数
    $NF:当前行的最后一个字段的值
    $(NF-1):当前行的倒数第二个字段

    2)自定义变量
    命名:由字母、数字、下划线组成,不能以数字开头,不能使用关键字,最好见名知意
    变量名区分大小写
    变量可以先定义再使用,也可以直接使用
    例: # echo hello | awk '{num=5;pass="douniwan";print num,pass}'
    # 5 douniwan

    例: # echo hello | awk '{num=5;num+=1;print num}'
    # 6


    特殊用法--------------------------------------------

    AWK 选项 ‘BEGIN{动作1} 定址{动作2}END{动作3}’ 文件

    BEGIN : BEGIN 动作,是在读取文件内容之前执行的;打印头文件,定义初始变量...;begin中动作只运行一遍;
    begin可以不借助任何文件
    END : 在读取文件内容之后运行;打印尾部文件,只打印结果...;end中动作只运行一遍;必须借助文件。
    例:打印头文件
    #awk -F ":" 'BEGIN{print “the first”} {print $3+num} END{print "the end for first"}' pass.txt
    #the first
    #the end for first

    例: 打印最近登录用户中IP地址为192.168.0.2的有多少次
    last | awk 'BEGIN {num=0} $3=="192.168.0.2" {num++} END {print num}'
    *********
    例: 统计文件中第二例是“tom”的有多少行
    awk 'BEGIN {sum=0} $2=="tom" {sum++} END{print sum}' b.txt

    例: 统计文件中第三列数值的和
    awk -F ":" 'BEGIN {sum=0} {sum+=$3} END{print sum}' pass.txt

    awk中的运算:--------------------------------------

    算术运算:+ - * / % ** ---------通常处理动作
    比较运算:> < == != ---------通常为了定界(定界中有)
    逻辑运算: && || ! ---------通常为了定界(定界中有)
    位运算 :<< >> & | ~

    算术运算
    例: #echo hello | awk '{print 2+3}'
    #5
    例: #awk -F ":" '{print $1,$3+2}' pass.txt
    #root 2

    例: #awk -F ":" '{print $1,($3+$4)/2}' pass.txt
    #root 0

    例: 打印0~100中含有7的行
    方式一:seq 100 | awk '/.*7.*/ {print $0}'
    方式二:seq 100 | awk '$1~/7/' {print $1}
    例: 打印0~100中能被二整除的行
    seq 100 | awk '$1%2==0 {print $0}'


    定界---------------------------------------------

    单个正则表达式

    awk '/正则表达式1/ {处理动作} ' 文件名

    #df -Th | awk '//$/ {print $6}'
    #31%

    匹配正则 ~ (不匹配正则 !~)

    (可以匹配带特点的列)
    匹配文件中每一行第二列含有tom的有多少行
    #awk '$2~/tom/ {print $0}' a.txt

    两个正则表达式

    awk '/正则表达式1/,/正则表达式2/ {处理动作} ' 文件名

    awk -F ":" '/^root/,/^sync/ {print $0}' pass.txt

    比较运算

    (借助切片变量)
    awk -F ":" '$1="root" {print $0}' pass.txt

    awk -F ":" '$3>5 {print $0}' pass.txt

    awk -F ":" '$3>=500 && $1!="nfsnobody" && $1!="cacti" && $1!="nagios"{print $0}' /etc/passwd

    (借助NR变量)
    awk -F ":" 'NR==5 {print $0}' pass.txt

    特殊:awk -F ":" 'NR==3 || NR==5 {print $0}' pass.txt

    逻辑运算

    awk -F ":" '$3>=500 && $1!="nfsnobody" && $1!="cacti" && $1!="nagios"{print $0}' /etc/passwd

    特殊:awk -F ":" 'NR==3 || NR==5 {print $0}' pass.txt

    awk -F ":" 'NR>3 && NR<5 {print $0}' a.txt


    awk中流程控制语句

    1·awk与重定向

    将uid>500的用户名及uid保存到/laozhang/pass.txt文件中

    #awk -F ":" '$3>500 {print $1,$3 > "/laozhang/pass.txt"}' /etc/passwd

    -------输入重定向 getline

    getline 接收来自于标准输入、管道和文件(非当前处理文件)的数据,存入到一个变量中,再给awk使用

    # awk -F ":" '$3>500 {print $1,$3 > "/laozhang/pass.txt"}' /etc/passwd

    从标准输入读取一个数据,传给变量username,判断passwd文件中是否有这样的用户名,如果有,打印行号和用户名

    # awk -F":" 'BEGIN {getline name < "/dev/pts/1"}{if($1==name){print NR,$1}}' a.txt

    通过管道将命令结果传递给一个变量

    #awk 'BEGIN {"date" | getline abc} {print $0} END {print abc}' a.txt
    (文件结尾打印进入a.txt文件的系统时间)

    基本结构
    1、顺序结构
    2、分支判断 if
    3、循环结构 while for 循环控制语句:break continue exit next

    一、三元操作符

    如果条件为真,输出问号后面的结果,否则输出冒号后面的结果

    # awk -F: '{print $1":"($3>$4?"uid"$3:"gid"$4)}' pass
    (打印pass文件中每行的第三列和第四列最大的值)

    二、if语句

    格式:awk 选项 '定界 {if(条件){动作1} else if (条件){动作2} ... else {动作n}}' 文件列

    例:**********
    if双分支:
    打印文件中uid大于等于500的用户为普通用户;小于500为系统用户
    #awk -F ":" ' { if($3>=500){printf "%-10s 是普通用户 ",$1} else{printf "%-10s 是系统用户 ",$1} }' /etc/passwd

    if多分支:
    从终端读取变量值;对值进行判断
    echo haha | awk 'BEGIN{getline abc < "/dev/pts/0"} {if(abc>=90){print "优秀"} else if (abc>=80){print "良好"}else if(abc>=60){print "及格"}else {print "不及格"}}'

    三、循环
    功能:
    1)从行中取出每个字段,循环字段的 while
    2)遍历数组元素 for

    while语句:

    格式:awk 选项 '定界 {定义初始变量;while(条件){动作;循环变量更新}}' 文件

    例:
    判断每行每片字符长度大于6的打印出来
    #awk -F ":" '{i=1;while (i<=NF) {if(length($i)>6){print $i};i++}}' pass.txt
    ********************
    统计文件中每列中“sync”出现了多少次
    #awk -F ":" '{i=1;while(i<=NF){if ($i=="sync"){sum++};i++}} END{print sum}' pass.txt

    将文件内容的行,竖着打印出来
    #cat pass1.txt
    sync:loring:tom:lisi:100

    #awk -F ":" '{i=1;while ($i<=NF){print $i};i++}' pass1.txt
    sync
    loring
    tom
    lisi
    100

    for语句:

    格式:awk 选项 '定界 {for(变量列表) {动作}}'

    打印1~5
    #awk 'BEGIN {for(i=1;i<=5);i++) {print $i}}'

    用for语句实现
    统计文件中每列中“sync”出现了多少次
    #awk -F ":" '{for(i=1;i<=NF;i++) {if($i=="sync"){sum++}}} END{print sum}' a.txt

    awk打印99乘法表
    #awk 'BEGIN{for (i=1;i<=9;i++){for(j=1;j<=i;j++){printf "%d*%d=%d ",i,j,i*j};print " "}}'



    ----------- 数组 ------------

    数组----内存中一段连续的地址空间(多个有序元素(值)的集合) 可理解为变量

    数组中的术语:
    数组元素 值
    数组下标 跟元素对应的

    数组下标:一般从0开始的 ---awk 中

    name=(tom jerry laozhang laoli) 直接定义用空白分隔

    靠下标引用元素 ${name[下标]}

    echo ${name[0]} --> tom echo ${name[1]} --> jerry ........

    数组遍历
    echo ${name[*]} ---> tom jerry laozhang laoli

    打印有元素个数
    echo ${#name[*]} --> 4

    引用最后一个元素值
    echo ${name[${#name[*]}-1]} ---> laoli

    数组元素支持单个修改;添加
    name[2]=lisi


    shell中下标:数值 -->0 1 2 3 4...
    awk 中下标:数值 字符串
    # vim b.txt
    tom
    jerry
    tom
    tom
    jerry

    打印文件第一列出现tom次数
    # awk '$1=="tom"{sum['a']++} END{print sum['a']}' b.txt
    # 3

    打印文件中第一列不同的词出现的次数--------》》for(i in sum)为固定格式表示从sum数组元素中遍历值
    # awk '{sum[$1]++} END{for(i in sum){print i,sum[i]}}' b.txt
    # jerry 2
    # tom 3

    打印文件中所有 行;列 中 不同词出现的次数

    # awk -F ":" '{for(i=1;i<=NF;i++){count[$i]++}}END{for(i in count) {print i,count[i]}}' /etc/passwd
    #netstat -ant

    Proto Recv-Q Send-Q Local Address Foreign Address State
    tcp 0 0 0.0.0.0:445 0.0.0.0:* LISTEN
    tcp 0 0 192.168.0.24:445 192.168.0.96:51437 ESTABLISHED
    tcp 0 0 :::22 :::* LISTEN

    统计每种连接状态各有多少人
    # netstat -ant |awk '/tcp>/{state[$NF]++}END{for(i in state) {print i,state[i]}}'

    ESTABLISHED 4
    LISTEN 21

    统计第五段相同ip地址的访问次数
    # netstat -ant | awk '/^tcp>/{split($5,ip,":");count[ip[1]]++}END{for (i in count) {print i ,count[i]}}'

    11
    192.168.0.96 1
    192.168.0.23 3
    0.0.0.0 10

    其中split($5,ip,":")----> split为awk内置函数将第五段再以冒号分隔切片 ; ip为数组名称且默认1为第一个下标(在awk中)
    count[ip[1]]++ ------> ip[1]就为ip地址 count 再把IP地址当做下标 引用 相同自增。

    awk '/UUID/{fs[$4]++}END{for(i in fs) {print i,fs[i]}}' /etc/fstab

    awk 'BEGIN{weekdays["mon"]="monday";weekdays["tue"]="tuesday";for(i in weekdays) {print weekdays[i]}}'

    awk '{ip[$1]++}END{for(i in ip) {print i,ip[i]}}' /var/log/httpd/access_log

    awk -F ":" '{if($3%2!=0) next;print $1,$3}' /etc/passwd

  • 相关阅读:
    java反射详解
    Oracle创建视图权限不足(解决)
    SQL Server为啥使用了这么多内存?
    在cmd中运行android.bat报出空指针异常
    QTP生成随机数字+字母
    loadView和ViewDidLoad区别
    Bonjour(苹果电脑公司的服务器搜索协议商标名)
    |= 或赋值
    我见过的类
    UML 继承和接口实现
  • 原文地址:https://www.cnblogs.com/zhangshan-log/p/13745318.html
Copyright © 2020-2023  润新知