zoukankan      html  css  js  c++  java
  • sed和awk

    sed

    sed(Stream Editor) 流编辑器,用来处理文件的

    sed是一行一行读取文件内容并按照要求进行处理,把处理后的结果输出到屏幕

    1. 首先sed读取文件中的一行内容,把其保存在一个临时缓存区中(也称为模式空间)
    2. 然后根据需求处理临时缓冲区中的行,完成后把该行发送到屏幕上

    总结:

    1. 由于sed把每一行都存在临时缓冲区中,对这个副本进行编辑,所以不会直接修改源文件
    2. sed主要用来自动编辑一个或多个文件,简化对文件的反复操作,对文件进行过滤或转换操作

    sed使用方法

    sed常见的语法格式有两种,一种叫命令行模式,另一种叫脚本模式

    命令行格式

    sed [options] '处理动作' 文件名

    -e  进行多项(多次)编辑
    -n  取消默认输出  不自动打印模式空间
    -r  使用扩展正则表达式
    -i  原地编辑(修改源文件)
    -f  指定sed脚本的文件名
    

    常见处理动作

    以下所有的动作都必须在单引号里

    'p'  打印
    'i'  在指定行之前插入内容  类似vim里的大写O
    'a'  在指定行之后插入内容  类似vim里的小写o
    'c'  替换指定行所有内容
    'd'  删除指定行
    

    对文件进行增、删、改、查操作

    语法:sed选项 '定位+命令' 需要处理的文件

    1)打印文件内容

    sed '' a.txt # 对文件什么都不做
    sed -n 'p' a.txt # 打印每一行,并取消默认输出
    sed -n '1p' a.txt # 打印第1行
    sed -n '2p' a.txt # 打印第2行
    sed -n '1,5p' a.txt # 打印1到5行
    sed -n '$p' a.txt # 打印最后1行
    sed -n '/root/p' 1.txt #打印包含root的行
    

    2)增加文件内容

    i 地址定位的上面插入

    a 下面插入

    sed '$a99999' a.txt  文件最后一行下面增加内容
    sed 'a99999' a.txt  文件每行下面增加内容
    sed '5a99999' a.txt  文件第5行下面增加内容
    sed '$i99999' a.txt  文件最后一行上一行增加内容
    sed 'i99999' a.txt  文件每行上一行增加内容
    sed '6i99999' a.txt 文件第6行上一行增加内容
    sed '/^uucp/ihello' a.txt  以uucp开头行的上一行插入内容
    # 注意 如果要需要连续插入两行有两种方法
    # (1) 利用
    
    # (2) 输入  然后回车输入内容
    
    1. 修改文件内容

    c 替换指定的整行内容

    sed '5chello world' a.txt  替换文件第5行内容
    sed 'chello world' a.txt  替换文件所有内容
    sed '1,5chello world' a.txt  替换文件1到5行内容为一行hello world
    sed '/^user01/c888888' a.txt 替换以user01开头的行
    
    1. 删除文件内容
    sed '1d' a.txt  删除文件第1行
    sed '1,5d'  a.txt  删除文件1到5行
    sed '$d'  a.txt  删除文件最后一行
    sed -r '/正则匹配/d'
    

    对文件进行搜索替换操作

    语法:sed 选项 's/搜索的内容/替换的内容/动作' 需要处理的文件

    其中,s表示search搜索,斜杠/表示分隔符,可以自己定义;动作一般是打印p和全局替换g(不加默认只替换第一个)

    sed -n 's/root/ROOT/p' 1.txt  # 只替换第一个root
    sed -n 's/root/ROOT/gp' 1.txt
    sed -n 's/^#//gp' 1.txt # 将#开头的行删除
    sed -n 's@/sbin/nologin@itcast@gp' a.txt # 将/sbin/nologin@itcast替换成itcast  @为自定义分隔符
    sed -n 's//sbin/nologin/itcast/gp' a.txt
    sed -n '10s#/sbin/nologin#itcast#p' a.txt # 只替换第10行的内容
    sed -n 's@/sbin/nologin@itcast@p' 2.txt # 注意:搜索替换中的分隔符可以自己指定
    sed -n '1,5s/^/#/p' a.txt # 注释掉文件的1-5行内容
    sed -n 's/(10.1.1.)1/1254/gp' a.txt #将10.1.1.1替换成10.1.1.254 其中后面的1代表前面的10.1.1.
    

    其他命令

    r		# 从另外文件中读取内容
    w   # 内容另存为    sed '1,3w new.txt' 1.txt
    &   # 保存查找串以便在替换串中引用  和()相同  
        sed -n 's/^sync/#&/gp' 1.txt  将sync开头的那一行注释掉, 用&引用^sync
        sed -n 's(^sync)/#1/gp' 1.txt  与上一行等价
    =   # 打印行号
        sed -ne '/root/p' -ne '/root/=' 1.txt  # e表示多次编辑
        sed -n '/root/=;/root/p' 1.txt
    !   # 对所选行以外的所有行应用命令,放到行数之后
    q   # 退出    处理到这一行退出
    

    其他选项

    -e 多项编辑
    -r 扩展正则
    -i 修改原文件
    sed -ne '/root/=' -ne '/root/p' 1.txt
    sed -e '5ihello world' -e '8a哈哈哈哈' 1.txt -e '5=;8='
    
    # 过滤/etc/vsftpd/vsftpd.conf文件中以#开头和空行:
    grep -Ev '^#|^$' 1.txt
    sed -e '/^#/d' -e '/^$/d' 1.txt
    sed '/^#/d;/^$/d' 1.txt
    sed -r '/^#|^$/d' 1.txt
    
    过滤smb.conf文件中生效的行:
    sed -e '/^#/d' -e '/^;/d' -e '/^$/d' -e '/^	$/d' -e '/^t#/d' 1.txt
    sed -r '^(#|$|;|	#|	$)/d' 1.txt
    
    grep '^[^a-z]' 1.txt
    sed -n '/^[^a-z]/p' 1.txt
    
    # 过滤出文件中的ip地址
    grep -E '([0-9]{1,3}.){3}[0-9]{1,3}' 1.txt
    sed -nr '/([0-9]{1,3}.){3}[0-9]{1,3}/p' 1.txt
    
    ifconfig | sed -nr '/([0-9]{1,3}.)[0-9]{1,3}/p' | head -1|sed -r 's/([a-z:]|[A-Z	])//g' |
    sed 's/ /
    /g' | sed '/^$/d'
    
    ifconfig eth0 | sed -n '2p' | sed -n 's/.*addr:(.*) Bcast:(.*) Mask:(.*)/1
    2
    3/p'
    
    -i 选项 直接修改原文件
    sed -i 's/root/ROOT;s/stu/STU/' 1.txt
    sed -i '1,5s/^/#&' a.txt # 加注释
    注意:
    -n 不要与-i一起使用
    p命令 不要与-i一起使用
    

    sed结合正则使用

    sed 选项 'sed命令或者正则表达式或者地址定位' 文件名

    1. 地址用于决定对哪些行进行编辑,地址的形式可以是数字、正则表达式、或两者的结合
    2. 如果没有地址定位,sed将处理输入文件的所有行
    /key/  查询包含关键字的行  sed -n '/root/p' 1.txt
    /key1/,/key2/  匹配包含两个关键字之间的行  sed -n '/^adm/,/^mysql/p' 1.txt
    /key/,x  从匹配关键字的行开始到文件第x行之间的行(包含关键字所在行) sed -n '/^ftp/,7p'
    x,/key/  从文件第x行开始到与关键字的匹配行之间的行 
    x,y!  不包含x到y的行
    /key/!  不包括关键字的行  sed -n '/bash$/!p' 1.txt
    

    脚本格式

    用法

    # sed -f scripts.sh file   使用脚本处理文件
    建议使用  ./sed.sh  file
    
    脚本的第一行写上
    #!/bin/sed -f
    1,5d
    s/root/hello/g
    3i777
    5i888
    a999
    p
    
    注意事项
    1) 脚本文件是一个sed的命令行清单,'coomands'
    2) 在每行的末尾不能有任何空格,制表符(tab)或其他文本
    3) 如果在一行中有多个命令,应该用分号分隔
    4) 不需要且不可用引号保护命令
    5) #号开头的行为注释
    
    例子:
    #!/bin/sed -f
    2a
    *********************
    2,$s/stu/user/
    $a
    we insert a new line
    s/^[a-z].*/#&/
    
    #!/bin/sed -f
    3a*********************
    $chelloworld
    1,3s/^/#&/
    

    awk

    awk是一种编程语言,主要用在linux/unix下对文本和数据进行处理,是linux/unix下的一个工具,数据可以来自标准输入,一个或多个文件,或其他命令的输出。

    awk的处理文本和数据的方式:逐行扫描文件,默认从第一行到最后一行,寻找匹配的特定模式的行,并在这些行上进行你想要的操作

    gawk是awk的GNU版本,它提供了Bell实验室和GNU的一些扩展,linux系统中已经把awk链接到gawk

    作用

    1. awk用来处理文件和数据,是类unix下的一个工具,也是一种编程语言
    2. 可以用来统计数据,比如网站的访问量,访问的IP量等等
    3. 支持条件判断,支持for和while循环

    awk的使用方式

    命令行模式使用

    awk 选项 '命令部分' 文件名
    
    特别说明:
    引用shell变量需要用双引号引起
    luck_line=123456
    sed -i "/$luck_line/d" file
    

    常用选项

    • -F 定义字段分割符号,默认的分隔符是空格
    • -v 定义变量并赋值

    命名部分说明

    • 正则表达式,地址定位
    '/root/{awk语句}'   sed中:'/root/p'
    'NR==1,NR==5{awk语句}'   sed中:'1,5p'
    '/^root/,/^ftp/{awk语句}'   sed中:'/^root/,/^ftp/p'
    
    • {awk语句1;awk语句2;...}
    '{print $0;print $1}'    sed中:'p'
    'NR==5{print $0}'    sed中:'5p'
    注:awk命令语句间用分号间隔
    
    • BEGIN(文件处理前)...END(文件处理后)...
    'BEGIN{awk语句};{处理中};END{awk语句}'
    'BEGIN{awk语句};{处理中}'
    '{处理中};END{awk语句}'
    

    脚本模式使用

    脚本编写

    #!/bin/awk -f  定义魔法字符
    以下是awk引号里的命令清单,不要用引号保护命令,多个命令用分号间隔
    BEGIN{FS=":"}
    NR==1,NR==3{print $1"	"$NF}
    ...
    

    脚本执行

    方法1:
    awk 选项 -f awk的脚本文件 要处理的文本文件
    awk -f awk.sh filename
    
    sed -f sed.sh -i filename
    
    方法2:
    ./awk的脚本文件(或者绝对路径)  要处理的文件
    ./awk.sh filename
    ./sed.sh filename
    

    awk内部相关变量

    $0             当前处理行的所有记录
    $1,$2,$3...$n  文件中每行以间隔符号分割的不同字段       awk -F: '{print $1,$3}' # :分隔
    NF             当前记录的字段数(列数)               awk -F: '{print NF}'
    $NF            最后一列                            $(NF-1)表示倒数第二列
    FNR/NR         行号   用||(第1和第5行) 和,(1到5行)NR>=1 && NR<=5 连接
    FS             定义间隔符                          'BEGIN{FS=":"};{print $1,$3}'
    OFS            定义输出字段分隔符,默认空格            'BEGIN{OFS="	"};{print $1,$3}'
    RS             输入记录分隔符,默认换行               'BEGIN{RS="	"};{print $0}'
    ORS            输出记录分隔符,默认换行               'BEGIN{ORS="
    
    "};{print $1,$3}'
    

    常用内置变量举例

    awk -F: '/root/{print $1,$NF}' 1.txt # 匹配到包含root的行以:分隔的第一列和最后一列
    awk 'NR==1,NR==5;/^root/{print $0}' 1.txt
    #;前第一到第五行都要打印,后面开头为root的再打印一遍,逐行处理
    awk 'BEGIN{FS=":";OFS="@@@@"};{print $1,$NF}' 1.txt
    awk 'BEGIN{FS=":"};{print "用户名是"$1"@@@@@@@@@@"$NF}' 1.txt
    awk -F: 'BEGIN{RS="	"};{print $1}' 1.txt  #将输入中	分隔的看做一行
    

    awk工作原理

    awk -F: '{print $1,$3}' 1.txt

    1. awk使用一行作为输入,并将这一行赋给内部变量$0,每一行也可以称为一个记录,以换行符(RS)结束

    2. 每行被间隔符:(默认为空格或制表符)分解成字段(或域),每个字段存储在已编号的变量中,从$1开始

      问:awk如何知道用空格来分隔字段的呢?

      答:因为有一个内部变量FS来确定字段分隔符,初始时FS赋为空格

    3. awk使用print函数打印字段,打印出来的字段会以空格分隔,因为$1,$3之间有一个逗号,逗号比较特殊,它映射为另一个内部变量,称为输出字段分隔符OFS,OFS默认为空格

    4. awk处理完一行后,将从文件中获取另一行,并将其存储在$0中,覆盖原来的内容,然后将新的字符串分隔成字段并进行处理,该过程将处理所有行处理完毕

    awk进阶

    1. 格式化输出print和printf
    print函数 类似echo "hello world"
    data | awk '{print "Month: "$2 "
    Year: "$NF}' /etc/passwd # 默认以空格分隔
    
    printf函数 类似echo -n "hello world"
    awk -F: '{printf "%-15s %-10s %-15s
    ", $1,$2,$3}' /etc/passwd
    
    %s 字符类型  strings  %-20s
    %d 数值类型
    占15字符
    - 表示左对齐,默认是右对齐
    printf默认不会在行尾自动换行,要加
    
    
    1. awk变量定义
    awk -v NUM=3 -F: '{print NUM}' /etc/passwd # 会输出文件行数这么多行的3
    awk -v num=1 'BEGIN{print $num}'
    注意:
    awk中调用定义的变量不需要加$, 加了相当于$0 $1 $2这种分隔后的字段而不是定义的变量值
    
    1. awk中BEGIN..END使用

    BEGIN:表示在程序开始前执行

    END:表示所有文件处理完后执行

    用法:'BEGIN{开始处理前};{处理中};END{处理结束后}' # 不用同时存在

    1. awk和正则的综合运用
    ==		等于
    !=		不等于
    >			大于
    <			小于
    >=		大于等于
    <=		小于等于
    ~			匹配
    !~		不匹配
    !			逻辑非
    &&		逻辑与   逻辑运算符用来连接表达式
    ||		逻辑或
    
    awk -F: '/^lp/,NR==10{print $0}' passwd  # 打印从以lp开头到文件第10行
    awk -F: '/^root/ || /^lp/{print $0}' # 打印以root和lp开头的这两行
    awk -F: '/^root/;/^lp/{print $0}'  # ;分隔命令,默认打印 效果同上
    
    awk 'NR==1,NR==5;/^root/{print $0}' 1.txt # 打印1到5行,且以root开头的被多打印一遍,一行一行处理
    打印1-5行以root开头的行
    awk 'NR>=1 && NR<=5 && $0 ~ /^root/{print $0}' 1.txt # 匹配
    awk 'NR>=1 && NR<=5 && /^root/{print $0}'
    ifconfig eth0| grep Bcast|awk -F'[: ]+' '{print $4}' # 分隔符设为:和空格(一个或多个)
    ifconfig eth0| awk -F"[: ]+" '/inet addr/{print $4RS$6}'
    

    流程控制语句

    if 结构

    if语句:
    
    if [ xxx ];then
    xxx
    fi
    
    格式:
    awk 选项 '正则,地址定位{awk语句}' 文件名
    { if(表达式) {语句1;语句2;...} }
    awk -F: '{if($3>=500 && $3<=60000)} {print $1,$3}' passwd
    awk -F: '{if($3==0) {print $1"是管理员"}}' passwd
    awk 'BEGIN{if($(id -u)==0) {print "admin"} }'
    

    if...else结构

    if...else语句
    if [ xxx ];then
       xxxx
    else
       xxxx
    fi
    
    格式:
    {if(表达式) {语句;语句;...} else {语句;语句;...}}
    
    awk -F: '{ if($3>=500 && $3!=65534) {print $1"是普通用户"} else {print $1,"不是普通用户"}}' passwd
    

    if...elif...else语句

    if [ xxx ]
    	xxxx
    elif [ xxx ]
    	xxxx
    ...
    else
    	xxxx
    fi
    
    if...else if...else语句
    for ((i=1;i<=5;i++));do echo $i;done
    
    格式:
    { if(表达式1) {语句;语句;...} else if(表达式2) {语句;语句;...} else if(表达式3) {语句;语句;...} else {语句;语句;...} }
    awk 'BEGIN {for(i=1;i<=5;i++){print i}}
    计算1-5的和
    awk 'BEGIN{for(i=1;i<=5;i++)(sum+=i);{print sum}'
    
    

    while循环

    打印1-5
    i=1;while (($i<=5));do echo $i;let i++;done
    awk 'BEGIN{i=1;while(i<=5){print i;i++}}'
    打印1-5的和
    awk 'BEGIN{i=1;while(i<=5){sum+=i;i++};print sum}' # 定义变量默认为0
    

    嵌套循环

    for ((y=1;y<=5;y++))
    do
    	for ((x=1;x<=$y;x++))
    		do
    			echo -n $x
    		done
    echo
    done
    
    awk 'BEGIN{for(y=1;y<=5;y++){for(x=1;x<=y;x++){printf x};print}}'
    

    awk算数运算

    + - * / % ^
    可以在模式中执行计算,awk都将按浮点数方式执行算术运算
    awk 'BEGIN{print 1+1}'
    awk 'BEGIN{print 2**3}'
    awk 'BEGIN{print 2/3}'
    

    awk统计案例

    1. 统计系统中各种类型的shell
    • awk中关联数组不需要声明
    awk -F: '{ shell[$NF]++};END{for(i in shells) {print i,shells[i]}}' /etc/passwd
    
  • 相关阅读:
    svn笔记
    cakephpurl生成
    cakephp加载流程
    jquery validate使用方法
    我需要具备的知识和能力总结
    cakePHP国际化和本地化
    javascript片段收集
    ecmall一个典型的操作
    9. Technical Overview 技术概述
    42. Spring Security Dependencies春季安全依赖
  • 原文地址:https://www.cnblogs.com/demian/p/12567681.html
Copyright © 2011-2022 走看看