zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    数据绑定表达式语法(Eval,Bind区别)
    使用博客园的第一件事 自定义主题
    sql2000 跨服务器复制表数据
    使用UpdatePanel 局部刷新出现中文乱码的解决方法!!
    MMC不能打开文件MSC文件
    sql 日期 、时间相关
    loaded AS2 swf call function in AS3 holder
    Rewrite the master page form action attribute in asp.net 2.0
    100万个不重复的8位的随机数
    flash 中实现斜切变型
  • 原文地址:https://www.cnblogs.com/zhangshan-log/p/13745318.html
Copyright © 2011-2022 走看看