首页 > 技术文章 > shell中 sed 命令详解

itgiser 2021-03-12 14:15 原文

1. sed 工作模式

sed(Stream Editor) 流编辑器。对标准输出或文件逐行进行处理
第一种:stdout | sed [option] "pattern command"
第二种:sed [option] "pattern command" file

2. sed选项

选项 含义
-n 只打印模式匹配行
-e 直接在命令行进行sed编辑,默认选项
-f 将sed编辑动作保存到文件中,用-f指定这个编辑命令所在的文件
-r 支持扩展正则表达式
-i 直接修改文件内容
# demo.txt 文件内容
# I love python
# I love PYTHON
# I love java
# I love Hadoop
# I love go

$ sed 'p' demo.txt  # 此处的 p 为一个命令 表示打印输入,此处没有匹配模式,表示处理所有的文件内容,将原行也进行了输出
I love python
I love python
I love PYTHON
I love PYTHON
I love java
I love java
I love Hadoop
I love Hadoop
I love go
I love go
$ sed -n 'p' demo.txt # 只打印匹配的行,原来文件中的行不进行打印输入,默认文件的原行信息都进行打印
I love python
I love PYTHON
I love java
I love Hadoop
I love go
$ sed '/python/p' demo.txt # 这样打印匹配到的python,同时把原行信息也进行了打印
# 说明, python 匹配到了,所有输出完原行信息后,又输出了一遍匹配到的行,其他的没匹配到,将原行直接输入
I love python
I love python
I love PYTHON
I love java
I love Hadoop
I love go
$ sed -n '/python/p' demo.txt # 加入-n 选项后,只打印匹配到的行,此处只有一个匹配模式-e可以省略
I love python
$ sed -n -e '/python/p' -e '/PYTHON/p' demo.txt # -e选项是默认的,但有多个匹配模式的时候,必须写上
I love python
I love PYTHON

# -f 指定编辑模式命令所在文件
$ vim edit.sed # 新建文件并写入内容 /python/p
/python/p
$ sed -n -f edit.sed demo.txt
I love python

# -r 扩展正则表达式
$ sed -n -r '/python|PYTHON/p' demo.txt
I love python
I love PYTHON

# -i 直接修改文件内容
$ sed -n 's/love/LOVE/g;p' demo.txt # 此处使用了 2个命令 g 和 p,但此时没有修改原文件,需要修改原文件使用 -i
I LOVE python
I LOVE PYTHON
I LOVE java
I LOVE Hadoop
I LOVE go
$ sed -i 's/love/LOVE/g;p' demo.txt # 将原来的文件中love修改成大写的LOVE
# 如果使用的是苹果的macos系统,就是在-i指令后面多加一个''空格即可
# sed -i '' 's/love/LOVE/g' demo.txt
$ cat demo.txt # 文件全部替换成功
I LOVE python
I LOVE PYTHON
I LOVE java
I LOVE Hadoop
I LOVE go

3. sed中的pattern

匹配模式 含义
10command 第10行进行匹配,其余行不进行匹配
10,20command 从第10行开始(含),到第20行结束(含)
10,+5command 从第10行开始(含),到15行结束(含),除了第10行外再加5行进行匹配
/pattern/command 进行pattern匹配,实际工作中用的最多
/pattern1/,/pattern2/command 匹配从pattern1的行开始,到匹配到pattern2的行结束
10,/pattern2/command 匹配从第10行开始,到匹配到pattern2的行结束
/pattern/,10command 匹配从pattern1的行开始,到第10行结束
# 还是前面的demo.txt
$ sed -n '3p' demo.txt # 打印输出第三行
I LOVE java
$ sed -n '2,4p' demo.txt # 打印输出第2行开始,第4行结束
I LOVE PYTHON
I LOVE java
I LOVE Hadoop
$ sed -n '2,+2p' demo.txt # 从第2行开始,往后加2行
I LOVE PYTHON
I LOVE java
I LOVE Hadoop

# 有特殊字符 需要转译
$ sed -n '/\/var\/empty/p' /etc/passwd # 匹配 /var/empty 但是包含 / 需要进行转译

$ sed -n '/^root/p' /etc/passwd # 匹配以 root开头的行

$ sed -n '/^root/p' /etc/passwd # 匹配以 root开头的行

$ sed -n '/^root/,/^_www/p' /etc/passwd # 匹配开始以root开头的行,到以_www开头的行进行结束

$ sed -n '11,/^_www/p' /etc/passwd # 从第11行开始匹配(包含),到以_www开头的行进行结束(包含)

4. sed的编辑命令

类别 编辑命令 含义
查询 p 打印
增加 a 行后追加
增加 i 行前追加
增加 r 外表文件读入,行后追加
增加 w 匹配行写入外部文件,将匹配的文件写入到新文件
删除 d 删除匹配到行
修改 s/old/new/= 只显示匹配到的行号
修改 s/old/new/ 将行内第一个old替换成new,一行中出现多个匹配,只替换第一个
修改 s/old/new/g 将匹配到的全部的old替换成new
修改 s/old/new/2g 将行内第2个开始的后所有的old替换成new
修改 s/old/new/ig 将行内old全部替换成new,忽略大小写
修改 s/old/new/2 表示将匹配到的行中的第二个old替换成new,第二个匹配到的进行替换
# 拷贝一份 passwd 文件进行操作, 千万不要操作 /etc/passwd 文件
# 删除
$ sed '1d' passwd # 删除1行 但只是打印输出了,不会对原文件进行操作
$ sed -i '1,10d' passwd # 删除从第1行到第10行 并保存 -i 对原文件操作
# 苹果系统 sed -i '' '1,10d' passwd

# a 行后追加的模式 append
$ sed -i '/\bin\bash/a this is new line' passwd # 匹配 /bin/bash的行,并在匹配到的行后添加一行 this is new line
# i 行前追加的模式 insert 
$ sed -i '/\bin\bash/i this is new line' passwd # 匹配 /bin/bash的行,并在匹配到的行前添加一行 this is new line
# r 从文件读取内容 然后行后追加 read r后面可以是绝对路径也可以是相对路径
$ sed -i '/\bin\bash/r demo.txt' passwd
# w 将匹配到的内容 写入到另外的文件中 write 保存到 /tmp路径下的newfile.txt
$ sed -i '/\bin\bash/w /tmp/newfile.txt' passwd

# 现在有这么个文件, python 其中两个单词写错了,需要修改
$ cat demo.txt 
I LOVE python
I pyxxon PYTHON pyxaon
I LOVE java pycaon
HADddP HADOOP

##  .. 代表2个任意的字符
$ sed -i 's/py..on/python/g' demo.txt
# macos 下 sed -i '' 's/py..on/python/g' demo.txt
$ cat demo.txt
I LOVE python
I python PYTHON python
I LOVE java python
HADddP HADOOP

# 反向引用, 引用匹配到的内容 还是这个文件,将py**on 这样的字符后面加上[hello]这个字符串
$ cat demo.txt 
I LOVE python
I pyxxon PYTHON pyxaon
I LOVE java pycaon
# 反向引用 & 这个代表匹配到的内容 也可以使用	\1 & 代表所有的匹配内容 \1 只是匹配括号内容的引用
# & 代表匹配到的所有内容 \1 需要加上括号 只是匹配括号内容的引用
$ sed -i 's/py..on/&hello/g' demo.txt
# macos sed -i '' 's/py..on/&hello/g' demo.txt
cat demo.txt
I LOVE pythonhello
I pyxxonhello PYTHON pyxaonhello
I LOVE java pycaonhello
# 括号也需要转译 
$ sed -i 's/\(py..on\)/\1hello/g' demo.txt

# 反向引用示例 将原来加入hello的文件进行处理
$ sed -i 's/\(py\)........./\1thon/g' demo.txt
$ cat demo.txt
I LOVE python
I python PYTHON python
I LOVE java python

# 双引号,当模式总需要引入外面定义的变量的时候,需要使用双引号
$ VAR1=python
$ VAR2=nodejs
$ sed -i "s/$VAR1/$VAR2/g" demo.txt
# 如果还是使用单引号 需要 把 变量引用也用单引号包围,建议直接使用双引号
$ sed -i 's/'$VAR1'/'$VAR2'/g' demo.txt

推荐阅读