Linux系统Shell文本处理(grep, sed和awk等)

简谈linux文本处理-sed

2018-02-11  本文已影响17人  思考问题的熊

文本处理能力是Linux强大优势之一,其中grep,sed和awk被称为Linux文本处理三板斧。grep 主要配合正则表达是来查找内容,在之前的文章里有提及,这篇文章则浅谈sed使用。

sed

sed工作流:读取$\to$执行命令$\to$显示。默认情况,所有的命令都会一个叫做在模式空间(pattern buffer)的缓冲区进行。因此不会改变原始输入文件的内容。

语法规则

sed即支持在命令行中用单引号输入执行命令,也支持执行含有sed命令的文件。使用方式如下:

sed [‐n] [‐e] 'command(s)' files
sed [‐n] ‐f script files

选项

sed 后面首先需要跟参数,支持的参数有:

选项与参数:
-n :禁止显示所有输入内容,只显示经过sed处理的行(常用)
-e :直接在命令列模式上进行 sed 的动作编辑,接要执行的一个或者多个命令
-f :执行含有sed 动作的文件
-r :sed 的动作支持的扩展正则(默认基础正则)
-i :直接修改读取的文件内容,不输出。

作用区域

默认情况下,sed命令会作用于文本数据的所有行。如果只想作用于某些行时,则需要使用在命令通过行号或者文本过滤的方式前指明作用区域。

行号

使用数字行号时,类似于R中的向量子集提取。单独数字表示某一行,逗号分割指示行范围,另外m,+n表示从m行开始向下n行,m~n表示从m行开始的每n行。

例如sed ‐n '2~2 p' test.txt 输出偶数行,sed ‐n '1~2 p' test.txt输出奇数行内容。

文本过滤

'/pattern/ command'可以只在包含pattern 的行中执行命令。如sed ‐n '/hello/ p' test.txt只会打印出包含hello的行。sed ‐n '/hello/, /world/ p' test.txt 打印两者之间的所有行。

特殊情况下也可以将文本过滤和行号结合使用,sed ‐n '/hello/,+5 p' test.txt 打印第一次出现hello的下面5行

命令

p 复制

复制模式空间中的内容,如果不和-n参数连用,每一行都会在屏幕输出两次,一行正常输出一行复制,结合-n 参数后就可以打印需要的内容。

d 删除

没什么可以说的,支持按照行号或者匹配来删除。

i 插入

有的时候一个结果文件没有header,使用sed 可以轻松完成。在匹配位置之前插入内容。

sed '1i name\tlength\foldchange' test.txt

a 追加

和插入命令的区别在于在匹配位置后一行插入内容,,如果想在末尾插入一行信息时将$作为地址。

sed '$a auther:zhaofei' test.txt

c 行替换

有了行的删除插入和追加自然也就会有行替换。

sed '$c auther:zhaofei' test.txt

y 字符转换

sed中的y命令可以实现一一映射的字符替换(注意和s命令的区别)。

[address]y/inchars/outchars/
# inchars中的第一个字符会被转换为outchars中的第一个字符,第二个字符会被转换成outchars中的第二个字符
# 直持续到处理完指定字符。如果inchars和outchars的长度不同会报错

l 输出隐藏字符

类似与cat -A,但是显示隐藏字符形式不同。

w 写入新文件

增强版的cp,只复制自己想要的东西,也可以将一个文件按不同的筛选条件分开保存。

sed -n -e '/a/ w a.txt' -e '1,10 w b.txt' test.txt
sed '1,10d;w new.txt' test.txt

r 读取文件

如果现在a文件的某个地方插入b文件,如在第三行插入

sed '3r b.txt' a.txt

e 执行外部命令

首先要区别于参数-e,这个e是在''里面的命令

sed 'e echo "hello"' test.txt

i 反向执行

在命令前加!反向执行命令

sed '/hello/!d' test.txt

#效果和下面的命令一致

sed -n '/hello/p' test.txt

n 匹配行下移一行操作

提前读取当前行的下一行内容,并且覆盖当前模式空间中的行

seq 5 |sed '3{n;d}'

# 首先匹配到第三行,然后移动到第四行进行删除
# 所及结果是
1
2
3
5

seq 5 |sed 'n;d' #效果类似与输出奇数行
seq 5 |sed -n 'n;p' #效果类似与输出偶数行

= 打印行号

sed '/hello/!d;=' test.txt

s 替换

通用写法[address1[,address2]]s/pattern/replacement/[flags]

这里pattern部分支持正则匹配,flags包括n(替换第n个匹配项),g(全局替换),p(输出改变的行,结合-n),i(忽略大小写匹配),w(保存改变的行到新文件)。

如果要替换的的内容包括了/,第一种方式是使用\/进行转义,第二种方法是使用@ | ! ^作为分隔符。

有时候我们会对文件中的目录进行替换,可以下面的写法

pwd |sed 's@/home/zhaofei@/home/feizhao@'
pwd |sed 's^/home/zhaofei^/home/feizhao^'
pwd |sed 's|/home/zhaofei|/home/feizhao|'

pattern支持各种正则表示法,例如

^ 行首
$ 行尾
. 换行符之外的任意单个字符
? 匹配之前项0次或者一次
+ 匹配1次或者多次
* 匹配0次或者多次
{n} 匹配n次
{n,} 匹配至少n次
{m,n} 至少m,最多n
[] 匹配任意一个
[-] 匹配范围中的一个
[^] 排除字符
| 或者

# posix字符类
[:alnum:] 字母数字
[:alpha:] 字母
[:blank:] 空格制表符
[:digit:] 数字
[:lower:] 小写字母
[:upper:] 大写字母
[:punct:] 标点
[:space:] 所有空白符(换行符和回车)

# 元字符
\s 单个空白
\w 单词

在进行匹配替换时,我们有时候并不想删除匹配的内容,只是希望其以另一种形式和替换内容一起出现。在sed中,特殊字符&用来存储匹配模式中的内容。

例如

sed 's/[[:digit:]]/number = &/ test.txt

sed 单行命令

# 删除空行
sed '/^$/d'

#每行后增加空行
sed G

# 在每5行后增加一空白行
gsed '0~5G'


# 在匹配式样“regex”的行之后插入一空行
sed '/regex/G'

# 在匹配式样“regex”的行之前和之后各插入一空行
sed '/regex/{x;p;x;G;}'

# 过滤所有的html标签
sed 's/<[^>]*>//g ; /^$/d' html.txt

# cat

sed ''

# head

sed '10 q'

# Dos2unix

sed 's/^M$//'

# Unix2dos

sed 's/$/\r/'

# nl(添加行号)
# sed行号会独占一行
sed = input.file | sed 'N;s/\n/\t/'

# tee

sed ‐n 'p; w new.txt'

# grep

sed ‐n '/pattern/p'

# grep -v

sed ‐n '/pattern/p!'

# 计算行数

sed -n '$='

# 多个内容同时替换

sed 's/a\|b\|c/d/' tmp.txt

# 将每两行连接成一行

sed '$!N;s/\n/ /'

# 如果当前行以等号开头,将当前行并到上一行末尾
# 并以单个空格代替原来行头的“=”
sed -e :a -e '$!N;s/\n=/ /;ta' -e 'P;D'

# 显示包含“AAA”、“BBB”或“CCC”的行(任意次序)
sed '/AAA/!d; /BBB/!d; /CCC/!d'

参考资料1

参考资料3

参考资料2


加入靠谱熊基地,和大家一起交流
上一篇下一篇

猜你喜欢

热点阅读