首页 > 技术文章 > sed 、awk用法

liyongchao-0508 2017-08-28 17:57 原文

Sed 命令

sed是一种流编辑器,它是文本处理中非常中的工具,能够完美的配合正则表达式使用,功能不同凡响。处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”(pattern space),接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。接着处理下一行,这样不断重复,直到文件末尾。文件内容并没有 改变,除非你使用重定向存储输出。Sed主要用来自动编辑一个或多个文件;简化对文件的反复操作;编写转换程序等。

 

 

主要用法

 -格式1: 前置命令|sed [选项] ‘编辑指令’

 -格式2:sed [选项] ‘编辑指令’ 文件名称

 

 

 

常见命令选项

 -n :屏蔽默认输出(全部文本)

 -i :直接修改文件内容

-e :可指定多个处理动作

 -r :启用扩展的正则表达式,若与其他选项一起使用,应作为首个选项

 {} :可组合多个命令,以分号分隔

 

 

基本的处理动作:

 操作符          用途                   指令示例

    p              打印行                 2,4p    输出2、3、4行     2p;4p 输出2、4行

    d              删除行                2,4d  删除2-4行

    s           字符串替换            s/old/new/  将每行中第一个old替换为new

 

操作实例:

 

输出文本:

sed -n ‘p’ a.txt              输出所有行

sed -n ‘4p’ a.txt             输出第4行

sed -n ‘4,7p’ a.txt           输出第4-7行

sed -n ‘4,+10p’ a.txt         输出第4行及其后的10行内容

sed -n ‘/^bin/p’ a.txt        输出以bin开头的行

sed -n ‘p;n’ a.txt            输出奇数行

sed -n ‘n;p’ a.txt            输出偶数行

sed -n ’10,${n;p}’ a.txt      输出第10行至文件末尾的所有的奇数行

 

 

替换文本:

sed ‘s/xml/XML/’ a.txt        将每行中的第1个xml替换为XML

sed ‘s/xml/XML/3’ a.txt       将每行中的第3个xml替换为XML

sed ‘s/xml/XML/g’ a.txt       将每行中的所有的xml替换为XML

sed ‘s/xml//g’ a.txt          将文件中所有的xml删掉

sed ‘s/doc/&s/g’ a.txt        将文件中doc都替换为docs

sed ‘4,7s/^/#/’ a.txt         将第4-7行注释掉

sed ‘s/^#an/an/’ a.txt        解除以#an开头行的注释

 

 

删除文本:

sed ‘3,5d’ a.txt              删除3-5行

sed ‘/xml/d’ a.txt            删除所有包含xml的行

sed ‘/xml/!d’ a.txt           删除不包含xml的行

sed ‘/^install/d’ a.txt       删除以install开头的行

sed ‘$d’ a.txt                删除最后一行

sed ‘/^$/d’ a.txt             删除空行

sed ‘/^$/{n;/^$/d}’ a.txt     删除重复空行

 

 

应用实例:

去除URL中的文件目录:

echo "http://www.a.com/dddddda/1/2/3/a.mp4?aeafafa=23&afafa=23" |sed '{s/?.*//;s/http:\/\///}' | grep -o "/.*"

 

 

Awk命令:

Awk是一种程序性语言,它具有一般语言具有的功能。简单来说awk就是把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行各种分析处理。awk语言的最基本功能是在文件或者字符串中基于指定规则浏览和抽取信息,awk抽取信息后,才能进行其他文本操作。完整的awk脚本通常用来格式化文本文件中的信息。通常,awk是以文件的一行为处理单位的。awk每接收文件的一行,然后执行相应的命令,来处理文本。

 

 

命令格式:

-格式1:前置命令|awk  [选项] ‘[条件]{编辑指令}’

-格式2:awk  [选项] ‘[条件]{编辑指令}’  文件名

 

 

Awk环境变量:

变量

描述

$n

当前记录的第n个字段,字段间由FS分隔。

$0

完整的输入记录。

ARGC

命令行参数的数目。

ARGIND

命令行中当前文件的位置(从0开始算)。

ARGV

包含命令行参数的数组。

CONVFMT

数字转换格式(默认值为%.6g)

ENVIRON

环境变量关联数组。

ERRNO

最后一个系统错误的描述。

FIELDWIDTHS

字段宽度列表(用空格键分隔)。

FILENAME

当前文件名。

FNR

同NR,但相对于当前文件。

FS

字段分隔符(默认是任何空格)。

IGNORECASE

如果为真,则进行忽略大小写的匹配。

NF

当前记录中的字段数。(列数)

NR

当前记录数。(行数)

OFMT

数字的输出格式(默认值是%.6g)。

OFS

输出字段分隔符(默认值是一个空格)。

ORS

输出记录分隔符(默认值是一个换行符)。

RLENGTH

由match函数所匹配的字符串的长度。

RS

记录分隔符(默认是一个换行符)。

RSTART

由match函数所匹配的字符串的第一个位置。

SUBSEP

数组下标分隔符(默认值是\034)。

 

 

 

 

运算符:

运算符

描述

= += -= *= /= %=

赋值

?:

C条件表达式

||

逻辑或

&&

逻辑与

~ ~!

匹配正则表达式和不匹配正则表达式

< <= > >= != ==

关系运算符

空格

连接

+ -

加,减

* / &

乘,除与求余

+ - !

一元加,减和逻辑非

^ ***

求幂

++ --

增加或减少,作为前缀或后缀

$

字段引用

 

 

 

 

应用实例:

条件语句:

awk中的条件语句是从C语言中借鉴来的

ls -l |awk 'BEGIN {size=0;print "[start]size is ", size} {if($5!=4096){size=size+$5;}} END{print "[end]size is ", size/1024/1024,"M"}'

 

 

循环语句:

awk中的循环语句同样借鉴于C语言,支持while、do/while、for、break、continue,这些关键字的语义和C语言中的语义完全相同

awk -F ':' 'BEGIN {count=0;} {name[count] = $1;count++;}; END{for (i = 0; i < NR; i++) print i, name[i]}' /etc/passwd

 

 

 

Awk使用方法:

        awk '{pattern + action}' {filenames}

其中 pattern 表示 AWK 在数据中查找的内容,而 action 是在找到匹配内容时所执行的一系列命令。花括号({})不需要在程序中始终出现,但它们用于根据特定的模式对一系列指令进行分组。 pattern就是要表示的正则表达式,用斜杠括起来。

 

cat /etc/passwd |awk  -F ':'  '{print $1}'

awk工作流程是这样的:读入有'\n'换行符分割的一条记录,然后将记录按指定的域分隔符划分域,填充域,$0则表示所有域,$1表示第一个域,$n表示第n个域。默认域分隔符是"空白键"

 

cat /etc/passwd |awk  -F ':'  'BEGIN {print "name,shell"}  {print $1","$7} END {print "blue,/bin/nosh"}'

awk工作流程是这样的:先执行BEGIN,然后读取文件,读入有/n换行符分割的一条记录,然后将记录按指定的域分隔符划分域,填充域,$0则表示所有域,$1表示第一个域,$n表示第n个域,随后开始执行模式所对应的动作action。接着开始读入第二条记录······直到所有的记录都读完,最后执行END操作。

 

ls -l |awk 'BEGIN {size=0;} {size=size+$5;} END{print "[end]size is ", size}'

统计目录下文件字节大小

zcat access.log.gz |awk 'BEGIN {size=0;} {size=size+$10;} END{print "log size is ", size/1024/1024/1024*8/300  "Gbps"}'

可以用于统计日志中的带宽

 

匹配日志中区域运营商:

 

zcat access.log.gz|nali3 |awk  '$2 ~/.*浙江.*电信/  {print $0}'

 

 

awk应用实例:

  • $ awk '/^(no|so)/' test-----打印所有以模式no或so开头的行。
  • $ awk '/^[ns]/{print $1}' test-----如果记录以n或s开头,就打印这个记录。
  • $ awk '$1 ~/[0-9][0-9]$/(print $1}' test-----如果第一个域以两个数字结束就打印这个记录。
  • $ awk '$1 == 100 || $2 < 50' test-----如果第一个或等于100或者第二个域小于50,则打印该行。
  • $ awk '$1 != 10' test-----如果第一个域不等于10就打印该行。
  • $ awk '/test/{print $1 + 10}' test-----如果记录包含正则表达式test,则第一个域加10并打印出来。
  • $ awk '{print ($1 > 5 ? "ok "$1: "error"$1)}' test-----如果第一个域大于5则打印问号后面的表达式值,否则打印冒号后面的表达式值。

$ awk '/^root/,/^mysql/' test----打印以正则表达式root开头的记录到以正则表达式mysql开头的记录范围内的所有记录。如果找到一个新的正则表达式root开头的记录,则继续打印直到下一个以正则表达式mysql开头的记录为止,或到文件末尾。

推荐阅读