sed与awk

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了sed与awk相关的知识,希望对你有一定的参考价值。


sed

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

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

address表示地址范围:
4 第四行
$ 最后一行(需要用单/双引号括起来)

​在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, 23,...),表示替换第几个匹配的内容。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的正常控制流
  • sed与awk_分隔符

  • 步骤1到步骤4,周而复始。
  • 处理多行模式空间(N、D、P)

多行模式空间:

sed与awk_分隔符_02

单行模式命令

解释

多行模式命令

解释

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)是另一个文本缓冲区。模式空间和保持空间可以相互复制数据。相关命令如下:

命令

缩写

功能

hold

h

将模式空间的内容复制到保持空间,且覆盖原保持空间的内容。

Hold

H

将模式空间的内容追加到保持空间的尾部。

get

g

将保持空间的内容复制到模式空间,且覆盖原模式空间的内容。

Get

G

将保持空间的内容追加到模式空间的尾部。

Exchange

x

交换保持空间和模式空间的内容。

sed与awk_分隔符_03


命令(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)
  1. 实例

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

sed

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

nl /etc/passwd | sed 2,5d

只要删除第 2 行

nl /etc/passwd | sed 2d

要删除第 3 到最后一行

nl /etc/passwd | sed 3,$d

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

nl /etc/passwd | sed 2a drink tea

在第二行前插入

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

删除/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

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/

直接修改文件内容

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

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

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

元字符

需要转义的形式


\\ n, m \\

()

\\ ( \\ )

  1. 总结

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


awk

sed与awk_sed

  • 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
  • 用法二
awk -F  #-F相当于内置变量FS, 指定分割字符

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

# 或者使用内建变量
$ awk BEGINFS="," 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
  • 用法四
# 将awk脚本放入文件
$ awk
  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
  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=" $ "
  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 BEGINIGNORECASE=1 /this/ log.txt

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

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

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


以上是关于sed与awk的主要内容,如果未能解决你的问题,请参考以下文章

sed与awk用法

sed与awk

sed 与 awk

sed与awk

markdown SED与AWK学习

awk / sed:如果任何字段与模式匹配,则替换所有字段