sed与awk

sed
  1. 命令格式
  • 基本命令
sed [option] '[address[,address]][!]command[arguments]' [file]

command为编辑命令:
d 删除
p 打印 ( option搭配参数 -n 则只输出匹配的行 )
a 追加
i 插入
c 更改

address表示地址范围:
4	第四行
$	最后一行(需要用单/双引号括起来)
10,20	第10到第20行
3,$		第3到最后一行
/pattern1/,/pattern2/		模式patern1到模式patern2之间的行
1,/^$/		第一行到第一个遇到的空行
/^$/,$		空行到最后一行

在address后边的 ! 使sed将相应的命令command作用于所有与该地址不匹配的行。即该地址/范围不执行命令command。

  • 替换
sed [-in] '[address]s/pattern/replacement/flags' [file]

flags(在有意义的情况下可以组合使用):
n	1~512之间的一个数字,表示对本模式中指定模式第n次出现的情况进行替换
g	对模式空间的所有出现情况进行全局替换。当没有g时只有第一次出现会被替换。
p	打印模式空间的内容
w file	将模式空间的内容写到文件file中
2	一个数字(1, 2, 3,...),表示替换第几个匹配的内容。1为默认值。

replacement中的特殊字符
&	引用用正则表达式匹配的内容
\n	引用第n(1~9的数字)个分组内容(分组内容通过pattern中的“ \( ”和“ \) ”来指定)
  • 删除
sed '[address|pattern]d' [file]
删除address描述范围或者匹配pattern的行

如删除空行
sed -i '/^\s*$/d' file
  • 增删改
sed [address]a\
	text

sed [address]i\
	text

sed [address]c\
	text

这里的\用来转义行尾的回车换行符
  • 列表
显示文件中的不可显字符
sed -n '1,10p' -e 'l' node2.log
head node2.log | sed -e 'l'

在sed中不能使用ASCII值来匹配字符。

  • 命令集
使用的命令
sed -f <cmdsetfile> file

cat cmdsetfile
/UNIX$/{
	N
	s/\nSystem/Operating &/
	P
	D
}
命令集的多个命令也可以在命令行中使用;连接使用。
  1. 改变控制流顺序
  • sed的正常控制流

    步骤1到步骤4,周而复始。

  • 处理多行模式空间(N、D、P)

多行模式空间:

单行模式命令解释多行模式命令解释
d删除整个模式空间的内容,再读入新行。D只删除多行模式空间的第一行,不读入新行。命令集的第一条命令重新作用于模式空间的剩余内容。
n读入一行并覆盖原有内容。N读入新行并添加到模式空间现有内容之后。原有的行和新添加的行之间用换行符(\n)分割。^匹配模式空间中的第一个字符的开始位置,$匹配模式空间中的最后的换行符。
p在执行完所有命令后模式空间的内容会自动输出。sed -n选项抑制这个默认动作。此外,命令集中的最后一条命令无法执行时也不会默认输出(D命令就能达到这个效果)。此时需要p/P命令帮助输出。这里p命令会输出模式空间中的所有内容。P输出多行模式空间中的第一行(Line 1),行结尾是第一个\n。

注:sed命令的逐行读入过程与上述命令是独立的。即sed的读入一行在命令集读入一行的流程之外。

  • 采用保持空间来保存模式空间的内容并使它可以用于命令(H、h、G、g、x)

模式空间(Pattern Space)是当前输入行的缓冲区,而保持空间(Hold Space)是另一个文本缓冲区。模式空间和保持空间可以相互复制数据。相关命令如下:

命令缩写功能
holdh将模式空间的内容复制到保持空间,且覆盖原保持空间的内容。
HoldH将模式空间的内容追加到保持空间的尾部。
getg将保持空间的内容复制到模式空间,且覆盖原模式空间的内容。
GetG将保持空间的内容追加到模式空间的尾部。
Exchangex交换保持空间和模式空间的内容。


命令(H、h、G、g、x)中的每一个都可以利用一个地址来指定一行或者行范围。
小写字母命令改写目的缓冲区的内容,大写字母命令追加缓冲区的现有内容。
H命令在保持空间的内容之后放置一个换行符,且后边跟随模式空间的内容(即使保持空间是空的,换行符也被追加到保持空间中)。G命令在模式空间的内容之后放置一个换行符,且后面跟随保持空间的内容。
例子

grep "^\.XX" $* | sort -u |
#或者使用;来分割sed命令
sed '
h
s/[][\\*.]/\\$/g
x
s/^\.XX//
x
s/^\\\.XX\(.*\)$/^\\.XX \pp/
G
s/\n//
'
输出偶数行
sed -n 'n;p' file

输出奇数行
sed -n 'p;n' file

倒序输出
sed '1!G;h;$!d' file
其中的限定符:
1表示第一行,$表示最后一行
关于!的解释:
After the address (or address-range), and before the command, 
a !  may be inserted, which specifies that the command shall
only be executed if the address (or address-range) does not match.
  1. 实例

在testfile文件的第四行后添加一行,并将结果输出到标准输出,在命令行提示符下输入如下命令:

sed -e 4a\newLine testfile

将 /etc/passwd 的内容列出并且列印行号,同时,请将第 2~5 行删除!

nl /etc/passwd | sed '2,5d'
注:nl的空行不占行号,cat -n的空行要占行号。

只要删除第 2 行

nl /etc/passwd | sed '2d'

要删除第 3 到最后一行

nl /etc/passwd | sed '3,$d'

在第二行后(在第三行)加上“drink tea?”字样

nl /etc/passwd | sed '2a drink tea'
注:没有-e参数时命令要用两个单引号括起来,且命令与文本之间要用空格分割。

在第二行前插入

nl /etc/passwd | sed '2i drink tea'

如果是要增加两行以上,在第二行后面加入两行字,例如 Drink tea or … 与 drink beer?

nl /etc/passwd | sed '2a Drink tea or ......\
> drink beer ?'
注:行末的\不是续行,而是形成两行插入的文本。

将第2-5行的内容取代成为“No 2-5 number”

nl /etc/passwd | sed '2,5c No 2-5 number'

打印5-7行

nl /etc/passwd | sed -n '5,7p'

打印日志文件中时间戳“2019-08-18 15:11:08”开始到“2019-08-18 15:12:08”结束的行

sed -n '/2019-08-18 15:11:08/,/2019-08-18 15:12:08/p' log.txt
即打印行从第一个“2019-08-18 15:11:08 ......” 开始,到第一个“2019-08-18 15:12:08 ......”结束。

搜索 /etc/passwd有root关键字的行

nl /etc/passwd | sed -n '/root/p'
注:使用-n的时候将只打印包含匹配模式的行。

删除/etc/passwd所有包含root的行,其他行输出

nl /etc/passwd | sed  '/root/d'

搜索/etc/passwd,找到root对应的行,执行后面花括号中的一组命令,每个命令之间用分号分隔,这里把bash替换为blueshell,再输出这行:

nl /etc/passwd | sed -n '/root/{s/bash/blueshell/;p;q}' 
注:q表示退出处理。

sed的搜索替换与vim/vi中的搜索替换功能很类似,都形如:

sed 's/要被取代的字串/新的字串/g'

/sbin/ifconfig eth0 | grep 'inet addr' | sed 's/^.*addr://g' | sed 's/Bcast.*$//g'

一条sed命令,删除/etc/passwd第三行到末尾的数据,把bash替换为blueshell

nl /etc/passwd | sed -e '3,$d' -e 's/bash/blueshell/'
注:-e表示多点编辑,第一个编辑命令删除/etc/passwd第三行到末尾的数据,第二条命令搜索bash替换为blueshell。

直接修改文件内容

afile 内每一行结尾若为 . 则换成 !
sed -i 's/\.$/\!/g' afile

在 afile 最后一行加入 # This is a tes
sed -i '$a # This is a test' afile
  1. sed中正则表达式元字符

元字符中需要注意转义的字符

元字符需要转义的形式
{ }\ { n, m \ }
()\ ( \ )
  1. 总结

sed擅长以非交互的方式处理文件,尤其擅长处理大文件,而且长于以行为单位处理文本。


awk

  • BEGIN{ 这里面放的是执行前的语句 } — 对应 “开始”
  • END {这里面放的是处理完所有的行后要执行的语句 } — 对应 “结束”
  • {这里面放的是处理每一行时要执行的语句} —对应每一行的 “输入”

官方手册
http://www.gnu.org/software/gawk/manual/gawk.html

  1. 语法
awk [-v var=value[-F..]] 'pattern {action}' var=value file(s)awk [-v var=value[-F ..] -f scriptfile var=value file(s) 

选项参数说明:

  • -F fs or --field-separator fs
    指定输入文件折分隔符,fs是一个字符串或者是一个正则表达式,如-F:。
  • -v var=value or --asign var=value
    赋值一个用户定义变量。
  • -f scripfile or --file scriptfile
    从脚本文件中读取awk命令。
  • -mf nnn and -mr nnn
    对nnn值设置内在限制,-mf选项限制分配给nnn的最大块数目;-mr选项限制记录的最大数目。这两个功能是Bell实验室版awk的扩展功能,在标准awk中不适用。
  • -W compact or --compat, -W traditional or --traditional
    在兼容模式下运行awk。所以gawk的行为和标准的awk完全一样,所有的awk扩展都被忽略。
  • -W copyleft or --copyleft, -W copyright or --copyright
    打印简短的版权信息。
  • -W help or --help, -W usage or --usage
    打印全部awk选项和每个选项的简短说明。
  • -W lint or --lint
    打印不能向传统unix平台移植的结构的警告。
  • -W lint-old or --lint-old
    打印关于不能向传统unix平台移植的结构的警告。
  • -W posix
    打开兼容模式。但有以下限制,不识别:/x、函数关键字、func、换码序列以及当fs是一个空格时,将新行作为一个域分隔符;操作符=不能代替=;fflush无效。
  • -W re-interval or --re-inerval
    允许间隔正则表达式的使用,参考(grep中的Posix字符类),如括号表达式[[:alpha:]]。
  • -W source program-text or --source program-text
    使用program-text作为源代码,可与-f命令混用。
  • -W version or --version
    打印bug报告信息的版本。
  1. 基本用法
  • 用法一
awk '{[pattern] action}' {filenames}   # 行匹配语句 awk '' 只能用单引号

# 每行按空格或TAB分割,输出文本中的1、4列
$ awk '{print $1,$4}' log.txt

# 格式化输出
$ awk '{printf "%-8s %-10s\n",$1,$4}' log.txt
  • 用法二
awk -F  #-F相当于内置变量FS, 指定分割字符

# 使用","分割
$  awk -F, '{print $1,$2}'  log.txt

# 或者使用内建变量
$ awk 'BEGIN{FS=","} {print $1,$2}'  log.txt

# 使用多个分隔符。先使用空格分割,然后对分割结果再使用","分割
$ awk -F '[ ,]'  '{print $1,$2,$5}'   log.txt
多个分割符还可以如下定义:
[ \t,:]
  • 用法三
awk -v  # 设置变量

$ awk -va=1 '{print $1,$1+a}' log.txt
$ awk -va=1 -vb=s '{print $1,$1+a,$1b}' log.txt
  • 用法四
# 将awk脚本放入文件
$ awk -f cal.awk log.txt
  1. 运算符
运算符描述
= += -= *= /= %= ^= **=赋值
?:条件运算符
││逻辑或
&&逻辑与
~ 和 !~匹配正则表达式和不匹配正则表达式
< <= > >= != ==关系运算符
空格连接
+ -加,减
* / %乘,除与求余
+ - !一元加,减和逻辑非
^ ***求幂
++ –增加或减少,作为前缀或后缀
$字段引用
in数组成员
过滤第一列大于2的行
$ awk '$1>2' log.txt

过滤第一列等于2的行
$ awk '$1==2 {print $1,$3}' log.txt

过滤第一列大于2并且第二列等于'Are'的行
$ awk '$1>2 && $2=="Are" {print $1,$2,$3}' log.txt 
  1. 内置变量
变量描述
$n当前记录的第n个字段,字段间由FS分隔
$0完整的输入记录
ARGC命令行参数的数目
ARGIND命令行中当前文件的位置(从0开始算)
ARGV包含命令行参数的数组
CONVFMT数字转换格式(默认值为%.6g)ENVIRON环境变量关联数组
ERRNO最后一个系统错误的描述
FIELDWIDTHS字段宽度列表(用空格键分隔)
FILENAME当前文件名
FNR各文件分别计数的行号
FS字段分隔符(默认是任何空格)
IGNORECASE如果为真,则进行忽略大小写的匹配
NF一条记录的字段的数目
NR已经读出的记录数,就是行号,从1开始
OFMT数字的输出格式(默认值是%.6g)
OFS输出记录分隔符(输出换行符),输出时用指定的符号代替换行符
ORS输出记录分隔符(默认值是一个换行符)
RLENGTH由match函数所匹配的字符串的长度
RS记录分隔符(默认是一个换行符)
RSTART由match函数所匹配的字符串的第一个位置
SUBSEP数组下标分隔符(默认值是/034)
# 输出顺序号 NR, 匹配文本行号
$ awk '{print NR,FNR,$1,$2,$3}' log.txt

# 指定输出分割符
$  awk '{print $1,$2,$5}' OFS=" $ "  log.txt
  1. 正则表达式应用
# 输出第二列包含 "th",并打印第二列与第四列
$ awk '$2 ~ /th/ {print $2,$4}' log.txt
~ 表示正则匹配开始。// 中是正则表达式。

# 输出包含"abc"的行
$ awk '/abc/' log.txt

# 输出不包含"abc"的行
$ awk '!/abc/' log.txt

# 不包含abc的单词的行
$ awk '/\b((?!abc)\w)+\b/' log.txt

# 忽略大小写
$ awk 'BEGIN{IGNORECASE=1} /this/' log.txt

# 模式取反
$ awk '$2 !~ /th/ {print $2,$4}' log.txt
$ awk '!/th/ {print $2,$4}' log.txt
  1. 其他常见应用
# 计算文件大小
ls -l *.pl | awk '{sum+=$5} END {print sum}'

#使用内置函数
$ awk 'BEGIN{info="this is a test2012test!";print match(info,/[0-9]+/)?"ok":"no found";}'
这里的match为内置函数
  1. 总结

awk善于将一行文本按照列来进行处理。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值