Linux命令 sed


原文链接: Linux命令 sed

Sed 命令地址匹配问题总结
文本编辑的一点心得--sed篇

sed是非交互式的编辑器。它不会修改文件,除非使用shell重定向来保存结果。默认情况下,所有的输出行都被打印到屏幕上。
sed编辑器逐行处理文件(或输入),并将结果发送到屏幕。具体过程如下:
首先sed把当前正在处理的行保存在一个临时缓存区中(也称为模式空间),然后处理临时缓冲区中的行,完成后把该行发送到屏幕上。sed每处理完一行就将其从临时缓冲区删除,然后将下一行读入,进行处理和显示。处理完输入文件的最后一行后,sed便结束运行。sed把每一行都存在临时缓冲区中,对这个副本进行编辑,所以不会修改原文件。

命令行参数:

-e 多点编辑
-i --in-place :直接修改文件内容((危险动作)),而不是输出到终端。
-E -r --regexp-extended :sed 的动作支持的是延伸型正规表示法的语法。(默认是基础正规表示法语法)
-n  加上 -n 参数后,则只有经过sed 特殊处理的那一行(或者动作)才会被列出来。

1. 定址

1、空(默认):表示在全文范围
2、单地址:
  n:指定行;
  /pattern/:被此模式所匹配到的每一行;
3、地址范围:
  n,N:从起始行到结束行
  n,+N:从第起始行,向后数多少行
  n,/par1/:从起始行到pat1第一次匹配到的行
  /pat1/,/pat2/:从pat1第一次匹配到的行到pat2第一次匹配到的行
  $:最后一行
 1,3表示1,2,3行,美元符号($)表示最后一行。

sed -n '17,+10p' /etc/hosts.deny

2. 定界符|分隔符

sed s指令后加@,#,$ /表示分隔符

echo this is a test line | sed 's/\w\+/[&]/g'
[this] [is] [a] [test] [line]

  1. s命令后面的第一个字段就是定界符,可以使用任意字符作为定姐夫@,#,$ / :| +
  2. sed 只替换匹配中的内容
  3. \w\+ 匹配每一个单词
  4. & 对应于之前所匹配到的单词
  5. ^ 从开头匹配
  6. .* 匹配任意字符
  7. # * 匹配#后面连续多个空格

3. 组合命令{} 命令分隔 ;

sed -i '9,${s/[ \t]*$/ /;s/^[ \t]*$//}' **/*.md

4. 指令

保持空间(hold space): 临时缓冲区
    sed每次执行时还拥有一个保持空间(hold space)缓冲区,用来临时保存内容,开始时默认是一个空行。
    保持空间用于保存模式空间的内容,模式空间的内容可以复制到保持空间,同样地保持空间的内容可以复制回模式空间。sed提供了几组命令用来完成复制的工作,其它命令无法匹配也不能修改模式空间的内容

    H: 保存 (Hold) 	h/H     将[模式空间pattern]的内容copy或者append到[保持空间hold --缓存区]
    G: 取回 (Get)     g/G   	将[保持空间hold]的内容copy或者append到[模式空间pattern]
    x: 交换 (Exchange) x 	    交换模式空间和保持空间的内容

模式空间(pattern space): [操作区,命令行]
    ! :命令前加!,给定界符取反,不在定界范围内才执行命令
    r : /path/from/filename:读取指定文件的内容,追加到当前模式空间后面
    = :显示行号    `sed -n '/music/=' quote.txt`

    a :新增, a [a\]或[a ]的后面可以接字串,而这些字串会在新的一行出现(操作行的下一行)~
    i :插入, i 的后面可以接字串,而这些字串会在新的一行出现(操作行的上一行);
    c :取代, c 的后面可以接字串,这些字串可以取代 n1,n2 之间的行!
    d :删除,因为是删除啊,所以 d 后面通常不接任何咚咚;
    p :列印,亦即将某个选择的数据印出。通常 p 会与参数 sed -n 一起运行~
    s :替换,可以直接进行取代的工作哩!通常这个 s 的动作可以搭配正规表示法!例如 1,20s/old/new/g 就是啦!
        修饰标记:
        /g:全局替换,没有此标记,只替换正则匹配到的第一项
        /w /PATH/TO/FILE:将替换后的内容保存一份至指定文件
        /p:将替换成功的内容送至标准输出
   多行模式空间的处理:
    n :读取文件下一行   到[pattern]模式空间中
    N :读取文件下一行追加到[pattern]模式空间中
    d :删除[pattern]模式空间中的行
    D :删除[pattern]模式空间中的所有行
    P :打印[pattern]模式空间中的第一行
一、标签
b label ,无条件跳转到标签label,如果label没有指定,跳转到命令的结尾
t label ,如果最后一次输入的最后一个 s/// 子命令执行成功,跳转到标签label,如果label没有指定,跳转到命令的结尾
:a                   #定义标签a
$!N                  #不是最后一行,执行N命令
/ms$/s/\n/ /         #如果以ms结尾,将\n替换为空格
ta                   #如果s///命令执行成功,跳转到标签a处
P                    #打印pattern space的第一行
D                    #删除pattern space的第一行,循环

#正则匹配:

^ 行的开始 如:/^sed/匹配所有以sed开头的行。
$ 行的结束 如:/sed$/匹配所有以sed结尾的行。
. 匹配一个非换行符的字符 如:/s.d/匹配s后接一个任意字符,然后是d。
* 匹配零或多个字符 如:`/ *sed/`匹配所有模板是一个或多个空格后紧跟sed的行。
[] 匹配一个指定范围内的字符,如/[Ss]ed/匹配sed和Sed。
[^] 匹配一个不在指定范围内的字符,如:/[^A-RT-Z]ed/匹配不包含A-R和T-Z的一个字母开头,紧跟ed的行。
\(..\) 保存匹配的字符,如s/\(love\)able/\1rs,loveable被替换成lovers。
& 保存搜索字符用来替换其他字符,如s/love/**&**/,love这成**love**。
  用来精确匹配一个单词 sed -n '/\<acc=701\>/'p
\< 锚定单词的开始,如:/\<love/匹配包含以love开头的单词的行。
\> 锚定单词的结束,如/love\>/匹配包含以love结尾的单词的行。

x\{m\} 重复字符x,m次,如:/0\{5\}/匹配包含5个o的行。
x\{m,\}重复字符x,至少m次,如:/o\{5,\}/匹配至少有5个o的行。
x\{m,n\}重复字符x,至少m次,不多于n次,如:/o\{5,10\}/匹配5--10个o的行。

经典案例


在sed命令中有许多的字符都被转义,比如\ , $, ^,单双引号还有点号等等,因此使用sed命令进行字符串的匹配和修改的时候,字符串中如果含有转义字符,很多情况下不能直接用字符本身表示。这时候可以使用反斜杠加上转义字符的方法来输出含转义字符的字符串,但这一方法并不是对所有的转义字符都有用,过程也较复杂。下面一一说明:

一般而言sed命令格式由三部分组成,sed + 功能选项 + 条件选项,功能选项由连接符号-加上代表不同功能的字母构成,条件选项表明对文本的筛选和处理条件,一般括在单引号或者双引号中。但两种引号在sed命令处理的过程中略有不同:
单引号:对其中的内容不做任何处理,即引号内的内容是sed命令定义的格式,对于在条件选项中使用的转义字符需要使用反斜杠加转义字符才能输出。例如:
若定义变量 temp=/home/test/, var=aa

echo $temp | sed 's/\//$var/g'
输出结果为:$varhome$vartest$var
你可能会发现并不是所有的转义字符都需要加反斜杠来输入(如上例中的$符号),这取决于转义字符在条件选项中的位置,如果在这个位置字符本身转义起作用,则需要加反斜杠。即sed命令先检查字符转义功能是否成立,若有转义功能则使用转义功能,否则按字符输出。如果你想要输出该字符时不确定该字符是否会转义,可以对所有位置添加反斜杠。

双引号:会对其中的变量进行直接转换,同样是上例,如果写成:

echo $temp | sed “s/\//$var/g”
则输出结果为:aahomeaatestaa
可以看出双引号将变量名直接替换成变量内容。

要想使用单引号得到上面双引号的输出结果也是可以做到的,这时候需要对变量名加单引号来处理:

echo $temp | sed 's/\//'$var'/g'
同样可以得到输出结果为:aahomeaatestaa

对于sed命令,如上例单引号命令>echo $temp | sed 's/\//$var/g' 中,我们对斜杠符号的输出加上了反斜杠,以免被sed命令视为转义字符功能。我们还可以采用另一种方法无需使用加反斜杠来输出斜杠字符。在这个命令中,分隔符使用了斜杠(/),因此斜杠默认转义,sed中是可以使用其他符号作为分隔符的,如果不使用斜杠作为分隔符,则斜杠默认无转义功能,这时就不需要借助反斜杠来输出了:

echo $temp | sed 's#/#'$var'#g'
这里我们使用#来代替/当分隔符,因此/不再具有转义功能,无需再加反斜杠来辨识。同样可以得到上面的输出效果。分隔符对单引号和双引号作用一样。

若字符串中含有单引号,有的时候会发现加反斜杠还是得不到想要的字符串输出。比较简单的一个做法是字符串中有单引号时,功能选项部分用双引号括起来,这样不用加反斜杠可以直接输出字符。例如:

echo $temp | sed "s#/#'#g"
输出结果为:'home'test'
同理上例如果写成:>echo $temp | sed 's#/#\'#g',则会报错。因为单引号需要成对出现,否则sed命令无法知道第一个单引号究竟与第二个还是第三个单引号匹配。

若字符串中含有双引号时,功能选项部分用单引号括起来,也可以不使用反斜杠来输出双引号。

echo $temp | sed 's#/#"#g'
输出结果为:"home"test"
但是,与单引号不同的是,上例如果写成:>echo $temp | sed "s#/#\"#g",却不会报错。这也就很好的解决了如果字符串中同时有单双引号的时候该如何处理的问题。

在更加复杂的文本情况中,sed命令中的转义字符还有许多问题需要注意,需要根据具体情况采取不同的输出方法来解决问题。

打点计数实现 sed指定次数替换

sed ':a;N;$!ba;s/ABC/TARGET/X'
但这个方案有2个弊端:

1、需要将文本一次性读入到pattern space,如果文件很大,是不行的
2、如果指定字符串在同一行内出现多次,那么这个方法也是不行的

X是第X个,复杂的看tim的

sed '0,/a/b;s/a/b/;ta;b;:a;n;ba' urfile

是时候另辟蹊径了,下面介绍一下我的方法,我为其命名为“打点记数法”
主要的思路是这样的:

利用sed的hold space,当遇到匹配行时,向hold space里面“打一个.”,使用 . 的个数来记录匹配的次数
如果 . 的个数达到了要求,则执行相应的操作

sed '/a/{x;s/^/./; /^.{3}$/{x;s/a/b/;b}; x}' urfile
sed '/a/{x;s/^/./;/^.{4}$/{x;s/a/b/;b};x}' urfile
sed '/a/{x;s/^/./;/^.{5}$/{x;s/a/b/;b};x}' urfile

  1. sed '/a/{x;s/^/./; x} 交换->打点->换回来 实现计数,不修改文件内容
  2. /^.{3}$/{x;s/a/b/;b}; 统计点的个数达到 就x;s替换,完成后b到行尾
    我们可以看到,对于次数的增加,我们只需要调整需要匹配的数值即可。
    /origin/{ #匹配时,开始记数
    x; #交换pattern space与hold space
    s/^/./; #向hold space打一个 .
    /^.{3}$/{ #判断 . 的个数是否达到要求
    x; #如果达到要求,交换hold space与pattern space
    s/origin/now/ #进行替换
    b} #跳转到代码结束
    x} #交换hold space与pattern space


批量更改文件名

将所有大于1M,且后缀为txt或jpg的文件,由形如 book_20170101.txt、image_20170101.jpg 的文件改名为 20170101-book.txt、20170101-image.jpg

for file in `find . -size +1M -name "*_*.txt" -o -name "*_*.jpg"`
do
    newfile=`echo $file | sed 's/\([a-z]\+\)_\([0-9]\+\)./\2-\1./'`
    mv $file $newfile
done

sed 替换字符,但是带转义的不替换

sed -i '/^1/!s/1/X/g' ## 替换1为X但是行首的1不替换
sed '/\,/!s/,/\n/g' <<<$a >b.sh

谍中谍,sed中sed

匹配替换第三列''内容 key

'Key' => env('ms_door_key', '35gh6djhd8imd92ed'),
sed "/'Key'/s/'[^']*'/'123456'/3" config.php >> 'Key' => env('ms_door_key', '123456'),

[^']  匹配除'外的任意字符
/3    仅替换第三次匹配的内容

'Secret' => env(ms_door_secret),'9kd7dnc0667sni82n28dd'),
sed "/'Secret'/{s/'[^']*'/'222222222'/3;t;s//'222222222'/2}" config.php

显示第10行到最后的内容

cat /etc/passwd |sed -n '10,$p'
cat /etc/passwd |tail -n+10|head -n10
cat /etc/passwd |sed -n '10,19p'

sed 查找制定内容,并在其后插入多行内容

### 在指定内容后插入
RUN  sed -i '/client\]/a  max_allowed_packet = 48M ' /etc/mysql/my.cnf
###
RUN  sed -i '/mysqld\]/a   \
event_scheduler=ON   \n\
default-storage-engine=INNODB   \n\
#default-character-set=utf8    \n\
character-set-server = utf8    \n\
max_allowed_packet = 16M    \n\
wait_timeout	= 500    \n\
interactive_timeout	= 500    \n\
connect_timeout = 20    \n\
' /etc/mysql/my.cnf

2.行首为特定字符串(server开头的行)的行首添加字符“#”,注释掉以特定字符串为首的行。(替换功能)

sed -i ' s/^server/#server/g ' /etc/ntp.conf

3.判断文件中是否存在特定字符串如果存在则不再重复加入,如果不存在,就添加字符串。(重复添加命令只保留一次)

#! /bin/bash
grep -q '10.114.0.2'  /etc/hosts
if  [ $?  -eq  0 ];then
return
else
sed '$a\
10.114.0.2 l2 l02 w6\
10.114.0.4 l4 l04 w7\
' /etc/hosts
if

查找并删除匹配内容 之前|之后 所有的行

sed '0,/---/d' A.txt ## 删除开头到 --- 行 (包含 ---)
sed '/---/,$!d' A.txt ## 删除开头到 --- 行 (不包含 ---)

sed '/^title/,$!d' file ## 删除到 title 行 (不包含 title)
sed '/^title/,$d' file ## 从 title 开始删除 (包含 title)

#添加/移除注释
sed -i '/iptables/s/^#//' # 取消注释
sed -i '/iptables/s/^/#/' # 增加注释

ENV LS_SETTINGS_DIR /etc/logstash
sed -ri 's/^path\.config:/#&/g' "$LS_SETTINGS_DIR/logstash.yml";

批量替换

find . -name "*.htm" -type f -print | xargs sed -i 's#http://aywusq#https://aywusq#g'
find ./ -path "./file" -prune -o -name "*.htm" |xargs grep -ins bizchinalinyi

合并行

多空行合并为一行

sed '/^$/{N/^\n$/D'}
sed -i -rn 'h;n;:a;H;n;$!ba;g;s/(\n){2,}/\n\n/g;p' test.txt
!{$!ba}就是如果不满足前面的条件,就执行$!ba
{}就是把要执行的命令括起来
!{}就是括号里的都不执行

删除重复行 uniq 重行

只保留重复行中的第一行,其他行删除

sed '$!N; /^\(.*\)\n\1$/!P; D'
$!N; 不是最后一行 读取下一行到模式空间
两行合并到一行 匹配两行如果一样就删除

sed行首删除一个字符

sed行首添加一个字符

sed '1 a\string1\n\string2\n' /etc/passwd 在第1行后插入两行字符串。
sed '1 i\string1\n\string2\n' /etc/passwd 在第1行前插入两行字符串

# enable snd-soc-wmt-fm34
sed -i '/snd-soc-wmt-fm34/s/^#//' fs_patch/load_drivers.sh

# s/^#//表示将字符串开头的#字符替换为空(即去除行首的#字符)
# /snd-soc-wmt-fm34/表示匹配含有snd-soc-wmt-fm34字符串的行

# disable snd-soc-wmt-fm34 back
sed -i '/snd-soc-wmt-fm34/s/^/#&/' fs_patch/load_drivers.sh

# 这里和上面的删除操作唯一的不同就在于s/^/#&/部分。其中,^字符匹配行首,#字符是一般字符表示添加该字符

find . -name '*.php' -exec sed -rni 'h;n;:a;H;n;$!ba;g;s/(\n){2,}/\n\n/g;p' "{}" \;
################################################################################

匹配不替换 不匹配替换

sed '/^1/!s/1/X/g'

排序删除重复行

file='test.txt'
sort -n $file | uniq
sort -n $file | awk '{if($0!=line)print; line=$0}'
sort -n $file | sed '$!N; /^.∗\n\1$/!P; D'

移动行

一、把上面的某行移动到下面是容易的,用 h 存到保留区,用 G 取出就行了,例如,把第六行变成第九行:
sed '6{h;d};9G' #第6行存到暂存区并删除 第9行取出并追加
二、由于sed是按顺序读取文本,所以把下面的行移动到上面稍微复杂一些,例如,把第七行放到第二行:
sed -n '2!{p;d};:1;6!{N;b1};h;n;p;g;p'
前面的数字是移动后的位置,后面的数字是将要被移动的行数减一。

sed 转义单引号的问题

sed命令中,使用单引号来制定操作,如sed 's/regular/replace/'。如果想在单引号中转义单引号采用转义字符是不行的。解决的方法是把sed部分用单引号分割开,在外面转义。

如:A: nl /etc/passwd | sed '2a I\'am Dophi!' --------错误

  B: nl /etc/passwd | sed '2a I'\''am Dophi'    ---------正确,都是单引号,单引号之间没有空格

sed -i "s|\('debug' =>\) .*|\1 ${DEBUG},|" config.php

rvm采用国内镜像

sed -i -e 's/ftp.ruby-lang.org\/pub\/ruby/ruby.taobao.org\/mirrors\/ruby/g' ~/.rvm/config/db

多文件字符替換

sed 's/localhost/127.0.0.1/g' mysql_virtual_*.cf

删除一个文本文件中不包含某几个关键词的所有行

sed -i '/aa|bb|ggg/!d' a.txt

删除file文件所有包含某几个关键词的所有行

sed -i '/abc/d;/efg/d' a.txt // 删除含字符串"abc"或“efg"的行

将 #!/bin/bash 替换为 #!/usr/bin/env bash

sed -i '/#!/bin/bash: /d'

markdown 将行尾替换为两个空格

sed '9,s/[ \t]*$/ /g'
sed -i '9,$s/[!^$][ \t]*$/ /' **/*.md
sed -i '9,${s/\r//;s/[ \t]*$/ /;s/^[ \t]*$//}' **/*.md
sed -i '/^$/!s/[ \t]*$/ /' **/*.md # 空行不替换 ,非空行增加2个空格
sed -i '/^-*$/!s/[ \t]*$/ /' content/**/*.md # 除 空行 和 ---行 外其他行增加2空格
sed -i -e 's/\r//' -e '/./,/^$/!d' -e '/^-*$/!s/[ \t]*$/ /' content/**/*.md # 1. 转换格式为unix 2.连续空行合并 3. 除空行和---外,行尾添加空格
Makefile中需要对$进行转义 sed -i -e 's/\r//' -e '/./,/^$$/!d' -e '/^-*$$/!s/[ \t]*$$/ /' content/**/*.md

hexo 相关

匹配第二行的内容 并替换成当前日期

sed -i -u -E "2s#^date:.+#date: $(date "+%Y-%m-%d %H:%M:%S" )#g" sed.md

找到所有文章,并删除所有包含update:

find . -name "*.md" -type f -exec sed -i '/layout: /d' {} \;
find . -name "*.md" -type f -exec sed -i '/update: /d' {} \; # 删除 update: 行
find . -name "*.md" -type f -exec sed -i '3i update: ' {} \; # 第三行插入 update:
find . -name "*.md" -type f -exec sed -i '1{h;d};3G' {} \; # 下移2行
find . -name "*.md" -type f -exec sed -i '2h;3G' {} \; # 复制第2行
find . -name "*.md" -type f -exec sed -i 's/^category :/categories:/' {} \; # 替换category为categories

hexo2hugo

去重 删除重复的 --- 行

sed -e 'N; /^\(.*\)\n\1$/!P; D' ## 任意去重
sed -e 'N; /^\(---\)\n\1$/!P; D'

去除windows \r

sed -i 's/\r//g' **/*.md
sed -i '9,$s/$/ /g' **/*.md

0. 首行插入 ---

sed -i '1i ---' **/*.md

1. 修改date 格式为rfc3339

date: 2016-09-27T15:57:46+08:00 --> 2017-09-28T11:11:13+08:00
sed -i -E '/^date:/s/([0-9]{4}-[0-9]{2}-[0-9]{2})[ T]([0-9]{2}:[0-9]{2}:[0-9]{2})(\+[0-9]{2}:[0-9]{2})?/\1T\2+08:00/' **/*.md

2. 实现添加[]并将里面的空格替换为, (合并下面两条命令)

  tags: arp,linux --> tags: [arp,linux]

sed -i -E -e '/^categories:/{s# ([^\r\n\t]*)# [\1]#;s/ /,/2g}' -e '/^tags/{s# ([^\r\n\t]*)# [\1]#;s/ /,/2g}' **/*.md
## categories 修正为数组

` sed -i -E -e '/^categories:/s# ([^\r\n\t]*)# [\1]#' -e '/^tags/s# ([^\r\n\t]*)# [\1]#' *.md `

## 从第二个空格起替换为,

`sed -E '/categories: /s/ /,/2g' *.md`

在第3行插入

sed -i '3i update: 2016-01-01' *.md
#
sed -i '1d' *.md

在文件首行前 加入指定文字

sed -i '1i title: 内存对齐\ndate: $dt\ncategories: 朴素linux\ntags: linux\n---\n' *.md

批量在行尾添加空格

find . -type f -name '*.php' -exec sed '$a\\n' {} \;
1) # sed '/$/a\n' test.txt,可以在文件的每行末尾添加一个回车
2) # sed '$a\eof' test.txt,可以在文件的末尾添加'eof'

删除全部空行 包括空格

sed '/^ *$/d'test.txt
%s/^n//g 全局替换所有以回车开头的字符,替换为空。
%s/^n$//g 如果有多个连续的空行,想保留一行

替换部分

'DB_HOST' => 'localhost', // 服务器地址
DB_HOST=127.0.0.1 # 服务器地址
sudo sed -i -u -E "s#'DB_HOST'\s+=> '[a-zA-Z0-9._]+'#'DB_HOST' => '$DB_HOST'#g" config.php

获取本机的ip 192.168.1.100

  1. 将 IP 前面的部分予以删除
    ifconfig eth0 | grep 'inet addr' | sed 's/^.*addr://g'
    192.168.1.100 Bcast:192.168.1.255 Mask:255.255.255.0
  2. 将 IP 后面的部分予以删除
    ifconfig enp3s0 | grep 'inet addr' | sed 's/^.*addr://g' | sed 's/Bcast.*$//g'
    192.168.1.100

移除大部分的HTML标签(包括跨行标签)

sed -e :a -e 's/<[^>]*>//g;/

在某行的前一行或后一行添加内容

具休操作如下:

#匹配行前加
sed -i '/allow 361way.com/iallow www.361way.com' the.conf.file
#匹配行前后
sed -i '/allow 361way.com/aallow www.361way.com' the.conf.file

而在书写的时候为便与区分,往往会在i和a前面加一个反加一个反斜扛 。代码就变成了:

sed -i '/2222222222/a\3333333333' test.txt
sed -i '/2222222222/i\3333333333' test.txt

这就就可以很方便的看出要在某一行前或某一行后加入什么内容 。不过经常我记不住a 、i 那个是前那个是后。我的记法是a = after ,i = in front 。这样就知道 i 是前,a 是后了。不过官方的man文件里不是这样解释的,man文件里是这样解释的:

a
text Append text, which has each embedded newline preceded by a backslash.
i
text Insert text, which has each embedded newline preceded by a backslash.

而且其可以配合find查找的内容处理,如下:

find . -name server.xml|xargs sed -i '/directory/i '

二、在某行(指具体行号)前或后加一行内容

sed -i 'N;4addpdf' a.txt
sed -i 'N;4ieepdf' a.txt

这里指定的行号是第四行 。

三、删除指定行的上一行或下一行

删除指定文件的上一行
sed -i -e :a -e '$!N;s/.*n(.*directory)/1/;ta' -e 'P;D' server.xml
删除指定文件的下一行
sed -i '/pattern="%/{n;d}' server.xml

这个写起来有点长,一般如果不是shell里的需要,我更喜欢用vim去处理。另外需要注意的是,在vim里如果替换的内容里tab这样的符号是需要在编辑模式下分别按ctrl+v 和crtl+I ,而不是不停的几个空格。

1、定位行:
sed -n '12,~3p' pass #从第12行开始,直到下一个3的倍数行(12-15行)
sed -n '12,+4p' pass #从第12行开始,连续4行(12-16行)
sed -n '12~3p' pass #从第12行开始,间隔3行输出一次(12,15,18,21...)
sed -n '10,$p' pass #从第10行至结尾
sed -n '4!p' pass #除去第4行

2、正则:'/正则式/'
sed -n '/root/p' /etc/passwd
sed -n '/^root/p' /etc/passwd
sed -n '/bash$/p' /etc/passwd
sed -n '/ro.t/p' /etc/passwd
sed -n '/ro*/p' /etc/passwd
sed -n '/[ABC]/p' /etc/passwd
sed -n '/[A-Z]/p' /etc/passwd
sed -n '/[^ABC]/p' /etc/passwd
sed -n '/^[^ABC]/p' /etc/passwd
sed -n '/<root/p' /etc/passwd
sed -n '/root>/p' /etc/passwd

3、扩展正则:
sed -n '/root|yerik/p' /etc/passwd #拓展正则需要转义
sed -nr '/root|yerik/p' /etc/passwd #加-r参数支持拓展正则
sed -nr '/ro(ot|ye)rik/p' /etc/passwd #匹配rootrik和royerik单词
sed -nr '/ro?t/p' /etc/passwd #?匹配0-1次前导字符
sed -nr '/ro+t/p' /etc/passwd #匹配1-n次前导字符
sed -nr '/ro{2}t/p' /etc/passwd #匹配2次前导字符
sed -nr '/ro{2,}t/p' /etc/passwd #匹配多于2次前导字符
sed -nr '/ro{2,4}t/p' /etc/passwd #匹配2-4次前导字符
sed -nr '/(root)*/p' /etc/passwd #匹配0-n次前导单词

4、sed编辑(对行的插入、删除、替换操作)
sed '/root/a admin' /etc/passwd #在root行后追加一个admin行
sed '/root/i admin' /etc/passwd #在root行前插入一个admin
sed '/root/c admin' /etc/passwd #将root行替换为admin
sed '/root/d' /etc/passwd #删除含有root的行

s替换
sed -n 's/root/admin/p' /etc/passwd
sed -n 's/root/admin/2p' /etc/passwd #在每行的第2个root作替换
sed -n 's/root/admin/gp' /etc/passwd
sed -n '1,10 s/root/admin/gp' /etc/passwd
sed -n 's/root/AAA&BBB/2p' /etc/passwd #将root替换成AAArootBBB,&作反向引用,代替前面的匹配项
sed -ne 's/root/AAA&BBB/' -ne 's/bash/AAA&BBB/p' /etc/passwd #-e将多个命令连接起来,将root或bash行作替换
sed -n 's/root/AAA&BBB/;s/bash/AAA&BBB/p' /etc/passwd #与上命令功能相同
sed -nr 's/(root)(.)(bash)/\3\2\1/p' /etc/passwd #将root与bash位置替换,两标记替换
或sed -n 's/(root)(.
)(bash)/\3\2\1/p' /etc/passwd
bash:x:0:0:root:/root:/bin/root

y替换
echo "sorry"|sed 'y/ory/ABC/' #一一对应替换(sABBC)

6、sed的模式空间和保持空间
h:模式---->保持
H:模式--->>保持
x:模式<--->保持
g:保持---->模式
G:保持--->>模式

例如:
111
222
333
444

sed '1h;2,3H;4G'

分析
CMD 模式 保持
111 111 \n
1h 111 111
----------->111
222 222 111
2,3H 222 111\n222
----------->222
333 333 111\n222
2,3H 333 111\n222\n333
----------->333
444 444 111\n222\n333
4G 444\n111\n222\n333
----------->444\n111\n222\n333

1-10
11-22
22-33
11-22
34-END

7、sed特殊用法
sed -n '/root/w a.txt' #将匹配行输出到文件
sed '/root/r abc.txt' /etc/passwd #把abc.txt的文件内容读入到root匹配行后
sed -n '/root/w a.txt'
sed -n '/root/{=;p}' /etc/passwd #打印行号和匹配root的行
sed -n '/root/{n;d}' /etc/passwd #将匹配root行的下一行删除
sed -n '/root/{N;d}' /etc/passwd #将匹配root行和下一行都删除
sed '22{h;d};23,33{H;d};44G' pass

8、sed 脚本编写方法
<1>从文件读入命令
sed -f sed.sh
sed.sh文件内容:
s/root/yerik/p
s/bash/csh/p

<2>直接运行脚本 ./sed.sh /etc/passwd
#!/bib/sed -f
s/root/yerik/p
s/bash/csh/p

###################################
二、Sed练习

1,删除文件每行的第一个字符。
sed -n 's/^.//gp' /etc/passwd
sed -nr 's/(.)(.)/\2/p' /etc/passwd
2,删除文件每行的第二个字符。
sed -nr 's/(.)(.)(.
)/\1\3/p' /etc/passwd

3,删除文件每行的最后一个字符。
sed -nr 's/.$//p' /etc/passwd
sed -nr 's/(.*)(.)/\1/p' /etc/passwd

4,删除文件每行的倒数第二个字符。
sed -nr 's/(.*)(.)(.)/\1\3/p' /etc/passwd

5,删除文件每行的第二个单词。
sed -nr 's/([^a-Z])([a-Z]+)([^a-Z]+)([a-Z]+)(.)/\1\2\3\5/p' /etc/passwd

6,删除文件每行的倒数第二个单词。
sed -nr 's/(.)([^a-Z]+)([a-Z]+)([^a-Z]+)([a-Z]+)([^a-Z])/\1\2\4\5\6/p' /etc/samba/smb.conf

7,删除文件每行的最后一个单词。
sed -nr 's/(.)([^a-Z]+)([a-Z]+)([^a-Z])/\1\2\4/p' /etc/samba/smb.conf

8,交换每行的第一个字符和第二个字符。
sed -nr 's/(.)(.)(.*)/\2\1\3/p' /etc/passwd

9,交换每行的第一个单词和第二个单词。
sed -nr 's/([^a-Z])([a-Z]+)([^a-Z]+)([a-Z]+)(.)/\1\4\3\2\5/p' /etc/samba/smb.conf

10,交换每行的第一个单词和最后一个单词。
sed -nr 's/([^a-Z])([a-Z]+)([^a-Z]+)([a-Z]+)(.)/\1\4\3\2\5/p' /etc/passwd

11,删除一个文件中所有的数字。
sed 's/[0-9]*//g' /etc/passwd

12,删除每行开头的所有空格。
sed -n 's/^\ *//p' /etc/samba/smb.conf
sed -nr 's/( )(.)/\2/p' testp

13,用制表符替换文件中出现的所有空格。
sed -n 's/\ /\t/gp' pass

14,把所有大写字母用括号()括起来。
sed -nr 's/([A-Z])/(&)/gp' testp
sed -n 's/[A-Z]/(&)/gp' testp

15,打印每行3次。
sed 'p;p' pass

16,隔行删除。
sed -n '1~2p' pass

17,把文件从第22行到第33行复制到第44行后面。
sed '1,21h;22h;23,33H;44G' pass

18,把文件从第22行到第33行移动到第44行后面。
sed '22{h;d};23,33{H;d};44G' pass

19,只显示每行的第一个单词。
sed -nr 's/([^a-Z])([a-Z]+)([^a-Z]+)(.)/\2/p' /etc/passwd

20,打印每行的第一个单词和第三个单词。
sed -nr 's/([^a-Z])([a-Z]+)([^a-Z]+)([a-Z]+)([^a-Z]+)([a-Z]+)(.)/\2--\4/p' /etc/passwd

21,将格式为 mm/yy/dd 的日期格式换成 mm;yy;dd
date +%m/%Y/%d |sed -n 's#/#;#gp'

22, 逆向输出
cat a.txt
ABC
DEF
XYZ
输出样式变成
XYZ
DEF
ABC

一、文本间距

二倍行距

sed G

在含空行的文件的行与行之间添加空行。输出文件的行与行之间的空行数不会多于一行。

sed '/^$/d; G'

三倍行距

sed 'G; G'

取消二倍行距(假定偶数行为空行)

sed 'n; d'

二、编号方式

标记行号(纯左对齐)。使用tab替代space可以保持页边距。

sed = filename | sed 'N; s/n/t/'

标记行号(号码在左,文本右对齐)。

sed = filename | sed 'N; s/^/ /; s/*(.{6,})n/1 /'

标记行号,但只输出非空的行。

sed '/./=' filename | sed '/./N; s/n/ /'

计算行数(类似于”wc -l”)

SED -N '$='

三、文本转换与替换

UNIX环境下:将DOS换行符转(CR/LF)换成Unix格式

sed 's/.$//' #假定所有行均以CR/LF结尾
sed 's/^M$//' #在bash/tcsh下,按Ctrl-V然后按Ctrl-M
sed 's/x0D$//' #gsed 3.02.80中可用,但第一个脚本更简单一些

UNIX环境下:将UNIX换行符转换成DOS格式

sed "s/$/'echo -e r'/" #ksh命令行模式下
sed 's/$'"/'echo r'/" #bash命令行模式下
sed "s/$/'echo r'/" #zsh命令行模式下
sed 's/$/r/' #gsed 3.02.80

DOS环境下:将Unix换行符(LF)转换成DOS格式

sed "s/$//" #方法一
sed -n p #方法二

DOS环境下:将DOS换行符(CR/LF)转换成Unix格式

#此操作不能在DOS版的sed中实现。转用tr来代替
tr -d r outfile #GNU tr version 1.22或以上

删除行首空白(space, tab),使文本全部左移。

sed 's/^[ t]*//' #请参照文末关于't'的注解

删除行末空白(space, tab)

sed 's/[ t]*$//' #请参照文末关于't'的注解

同时删除行首行尾空白(space, tab)

sed 's/^[ t]*//; s/[ t]*$//'

在每行行首插入5个空格(使页面右移)

sed 's/^/ /'

使文本全部靠右对齐(宽度为79列)

sed -e; a -e 's/^.{1, 78]$/ &/;ta'

使文本居中(宽度为79列)。

#方法一中,行首空格仍然有效,行尾被加上了空白以填补不足。
#方法二中,行首空白在居中过程中被抛弃,行尾也没有补白的空白。
sed -e :a -e 's/^.{1, 77}$/ &/;ta' #方法一
sed -e :a -e 's/^.{1, 77}$/ &/;ta' -e 's/( *)1/1/' #方法二

查找与替换:将每行中的”foo”替换成”bar”

sed 's/foo/bar/' #只替换每行中的第一个实例
sed 's/foo/bar/4′ #只替换每行中的第四个实例
sed 's/foo/bar/g' #替换一行中出现的所有实例
sed 's/(.*)foo(.*foo)/1bar2/' #替换每行倒数第二个实例
sed 's/(.*)foo/1bar/' #只替换替换每行倒数第一个实例

查找与替换:将不含”baz”的行中的”foo”替换成”bar”

sed '/baz/!s/foo/bar/g'

将”scarlet””ruby””puce”换为”red”

sed 's/scarlet/red/g; s/ruby/red/g; s/puce/red/g' #适用于大部分sed
gsed 's/scarlet|ruby|puce/red/g' #只适用于GNU的sed

颠倒行序(使末行变首行,首行变末行) (类似tac)

#HHsed的特性(或者是Bug)会导致空行被删除
sed '1!G;h;$!d' #方法一
sed -n '1!G; h; $p' #方法二

反序输出每一行(类似rev)

sed '/n/!G;s/(.)(.*n)/&21/;//D;s/.//' /*这里似乎有点问题*/

如果某行以反斜线结尾,则将下一行接在它的后面

sed -e :a -e '/$/N; s/n//; ta'

如果某行以等号开头,
则将它接在上一行的行尾,并将等号用一个空格来替换

sed -e :a -e '$!N; s/n=/ /; ta' -e 'P;D'

给数值字符串加逗点,如将”1234567″变为”1,234,567″

gsed ':a; s/B[0-9]{3}>/,&/;ta' #GNU sed
sed -e :a -e 's/(.*[0-9]([0-9]{3})/1,2/;ta' #其它sed

给带小数点和负号的数字加逗点(GNU sed)

gsed ':a;s/(^|[^0-9])([0-9]+)([0-9]{3}/12,3/g;ta'

每隔五行加入一个空行

gsed '0~5G' #只适用于GNU sed
sed 'n;n;n;n;G' #其它sed

四、选择输出特定的行

输出文件的前十行(与head类似)

sed 10q

输出文件和第一行

sed q

输出文件和末尾10行(与tail类似)

sed -e :a -e '$q; N;11, $D;ba'

输出文件的最后两行

sed '$!N; $!D'

输出文件的末行

sed '$!d' #方法一
sed -n '$p' #方法二

输出符合正则表达式的行(类似grep)

sed -n '/regexp/p' #方法一
sed '/regexp/!d/ #方法二

输出不符合正则表达式的行(类似grep -v)

sed -n '/regexp/!p' #方法一,其实现与上面的描述是一致的
sed '/regexp/d' #方法二,这样的语法更简单

输出某一正则表达式之前的一行,但不输出含有该正则表达式的行

sed -n '/regexp/{g;1!p;};h'

输出某一正则表达式之后的一行,但不输出含有该正则表达式的行

sed -n'/regexp/{n;p;}'

输出某一正则表达式之前和之后的一行,以及该正则表达式出现的行的行号(与”grep
-A1 -B1″)

sed -n -e '/regexp/{=;x;l!p;g;$!N;p;D;}' -e h

提取含AAA和BBB和CCC(任意顺序)的行

sed '/AAA/!d; /BBB/!d; /CCC/!d'

提取含AAA和BBB和CCC(按该顺序)的行

sed '/AAA.*BBB.*CCC/!d'

提取含AAA或BBB或CCC的行(类似于egrep)

sed -e '/AAA/b' -e '/BBB/b' -e'/CCC/b' -e d #适用于大部分sed
gsed '/AAA|BBB|CCC/!d' #只适用于GNU sed

输出含有AAA的段落(空行分隔段落)

#以下脚本在HHsed v1.5 中要在'x;'后加上'G;'
sed -e '/./{H;$!d;}' -e 'x; /AAA/!d;'

输出含AAA和BBB和CCC(任意顺序)的段落

sed -e '/./{H; $!d;}' -e 'x;/AAA/!d; /BBB/!d; /CCC/!d'

输出含AAA或BBB或CCC的段落

sed -e '/./{H;$!d;}' -e 'x;/AAA/b' -e '/BBB/b' -e '/CCC/b' -e d
gsed '/./{H;$!d;};x;/AAA|BBB|CCC/b;d' #只适用于GNU sed

输出长度不小于65个字符的行

sed -n '/^.{65}/p'

输出长度小于65个字符的行

sed -n '/^.{65}/!p' #方法一,其实现与上面的描述是一致的
sed '/^.{65}/d' #方法二,这样的语法更简单

输出从给定正则表达式到文件末尾的部分

sed -n '/regexp/,$p'

输出指定行号的部分(如输出8-12行,包括本身)

sed -n '8, 12p'

输出第52行

sed -n '52p' #方法一
sed '52!d' #方法二
sed '52q;d' #方法三(在文件较大时效率更高)

从第三行开始,每七行输出一次

gsed -n '3~7p' #只适用于GNU sed
sed -n '3,${p;n;n;n;n;n;n;} #适用于其它sed

输出两个正则表达式之间的部分(包含本身)

sed -n "/regexp1/,/regexp2/p' #大小写敏感

五、选择性删除特定行

输出除两正则表达式之间部分之外的全部

sed '/regexp1/,/regexp2/d'

删除重复、连续的行(类似uniq)

#一系列重复的行中的第一行将被保留,其余的被删除
sed '$!N; /^(.*)n1$/!P; D'

删除重复、不连续的行

#注意不要造成缓冲区溢出,否则使用GNU sed
sed -n 'G; s/n/&&/; /^([ -~]*n).*n1/d; s/n//; h; P'

删除文件的前十行

sed '1, 10d'

删除文件的末行

sed '$d'

删除文件的最后两行

sed 'N; $!P;$!D;$d'

删除文件的最后10行

sed -e :a -e '$d;N;2,10ba' -e 'P;D' #方法一
sed -n -e :a -e '1, 10!{P;N;D;};N;ba' #方法二

每8行删除一次

gsed '0~8d' #只适用于GNU sed
sed 'n;n;n;n;n;n;n;d;' #适用于其它sed

删除文件中连续的空行(只保留一个空行),包括开头和结尾 (类似cat
-s)

sed '/./,/^$/!d' #方法一,文件开头无空行,结尾保留一个空行
sed '/^$/N;/n$/D' #方法二,文件开头允许一个空行,结尾无空行

删除所有连续的空行,除了前两个之外

sed '/^$/N;/n$/N;//D'

删除文首所有的空行

sed '/./,$!d'

删除文末所有空行

sed -e :a -e '/^n*$/{$d;N;ba' -e '}' #适用于所有sed
sed -e :a -e '/^n*$/N;/n$/ba' #同上,但不包括gsed 3.02*

删除每一段落的最后一行

sed -n '/^$/{p;h;};/./{x;/./p;}'

六、特殊用法

去除man文档中的特殊字符(char,backspace)

#如果你使用Unix System V 或者 bash shell,'echo'命令需要一个'-e'参数
sed "s/.`echo b`//g" #Unix 环境下双引号是必需的
sed 's/.^H//g' #在bash/tcsh, 按Ctrl+V 然后按Ctrl+H
sed 's/.x08//g' #sed v1.5的十六进制表达式

获取Usenet/e-mail的头信息

sed '/^$/q' #删除第一个空行后的所有行

获取Subject头信息,但是要删除原始的”Subject:”部分

sed '/^Subject: */!d; s///;q'

获取返回地址头信息

sed '/^Reply-To:/q; /^From:/h; /./d;g;q'

为每一行行首添加一个尖括号和一个空格(引用)

sed 's/^ /> /'

删除行首的尖括号和空格(去除引用)

sed 's/^> //'

去除大部分HTML标签(适用于多行标签)

sed -e :a -e 's/<[^>]*>//g;/

提取多部分的UU编码的二进制文件,删除不必要的头信息,只留下UU编码的部分

#传送给sed的文件必须按适当的顺序
#版本一可以在命令行下输入
#版本二可以写成可执行的Unix脚本
sed '/^end/,/^begin/d' file1 file2 ... fileX | uudecode #版本一
sed '/^end/,/^begin/d' "$@" | uudecode #版本二

七、典型用法

sed接受一个或多个命令并按顺序对每一行输入执行全部这些命令。当所有的命令都对第一行执行以后,这一行被输出,然后开始对第二行进行处理,如此循环。前面的例子假定输入来自标准输入设备(如控制台,一般是通过管道的输入)。如果输入不来自stdin,可以在命令行中添加一个或多个文件名。输出将被送到标准输出设备。

如:

cat filename | sed '10q' #使用管道输入
sed '10q' filename #同样的效果,不过免去了使用cat
sed '10q' filename > newfile #重定向输出到磁盘

更多语法讲解,包括用包含编辑命令的文件来代替命令行输入,请参阅

  • 《sed&awk,2nd Edition》by Dale Dougherty & Arnold Robbins(O’Reilly,
    1997; http://www.ora.com)
  • 《UNIX Text Processing》by Dale Dougherty & Tim O’reilly(Hayden
    Books, 1987)

或者参考Mike Arst写的教程。

要想发掘出sed的全部力量,你必须懂得”正则表达式”。关于正则表达式,请参阅:

  • 《Mastering Regular Expressions》 by Jeffrey Freidl (O’Reilly, 1997)

Unix系统中的man手册也会有所帮助(试试”man sed”,”man regexp”,
或者看看”man
ed”中关于正则表达式的部分),不过man手册是出了名的难懂。它并不是用来教那些sed和正则表达式的初学者的,它是一个写给那些已经掌握了这些工具的人的手册。

八、引号的语法

以上的例子使用单引号而不是双引号来容纳编辑命令,因为sed通常用于Unix平台。单引号可以防止Unix
shell对’\$”`’这样的字符进行解释和展开,如果它们被包含在双引号中,那么这些就会发生。使用csh或其衍生而来的shell的人,即使是在单引号中,还需要把’!’前加上反斜线才能正确的运行上面的例子。DOS版本的sed总是要求用双引号而不是单引号来包含编辑命令。

九、在sed脚本中使用’t’

为了文档的清晰,我们使用了表达式’t’来代表一个脚本中的制表符。但是多数sed版本不识别’t’这个缩写,因此,在编写这些脚本时你要按TAB键。’t’这个缩写是为awk,perl,HHsed,sedmod,GNU
sed v3.02.80的正则表达式所支持的元字符。

十、sed的版本

sed的版本之间确不太一样,可能在语法上有些许的不同。具体说来,很多版本不支持编辑命令中的标签(:name)或分支符(b,t),除了尾部的这些元素。我们使用了可以为大多数sed用户移植的语法,尽管GNU版本的sed允许更简洁的语法。
当读者看到一个相当长的命令像:

sed -e '/AAA/b' -e '/BBB/b' -e '/CCC/b' -e d

知道GNU可以让你把它减缩为:

sed '/AAA/b;/BBB/b;/CCC/b;d' #或者更简单
sed '/AAA|BBB|CCC/b;d'

是很令人高兴的。

另外,记住:很多sed的版本接受这样的命令像”/one/ s/RE1/RE2/”,
有一些不允许”/one/!
s/RE1/RE2/”这样在’s’前包含空格的命令。这时,在输入命令的时候要去除空格。

十一、优化速度

当执行速度需要优化(由于输入文件很大或者处理器、CPU较慢)时,如果的替换命令前给出查找命令,替换操作会变得更快。如:

sed 's/foo/bar/g' filename #标准的替换操作
sed '/foo/ s/foo/bar/g' filename #这样执行起来更快
sed '/foo/ s//bar/g' filename #sed速记语法

在进行行的选择和删除操作时,如果你操作的行只是包含在文件前面的一部分时,在脚本中加入一个退出命令’q’会大幅缩减处理大文件的时间。如:

sed -n '45,50p' filename #输出45-50行
sed -n '51q; 45,50p' filename #同样的功能,但执行得更快
文本分隔:------
# 在每一行后面增加一空行。 sed G
# 在每一行后面增加两行空行。 sed "G;G"
# 删除文本中所有的空行。sed "/^$/d"
# 将原来的所有空行删除并在每一行后面增加一空行。sed "/^$/d;G"   这样在输出的文本中每一行后面将有且只有一空行。
# 将第一个脚本所产生的所有空行删除(即删除所有偶数行)。 sed "n;d"  在sed中用n表示奇数行,用p表示偶数行。
# 在每5行后增加一空白行 (在第5,10,15,20,等行后增加一空白行)。sed "n;n;n;n;G;"

# 在包含“regex”的行之前插入一空行。 sed "/regex/{x;p;x;}"  #插入两个空行sed "/regex/{x;p;p;x;}"
# 在包含“regex”的行之后插入一空行。 sed "/regex/G"        #插入两个空行sed "/regex/{G;G;}"
# 在包含“regex”的行之前和之后各插入一空行。 sed "/regex/{x;p;x;G;}"   #各插入两个空行sed "/regex/{x;p;p;x;G;G;}"

编号:------
# 为文件中的每一行进行编号(简单的左对齐方式)。使用“制表符”对齐边缘。 sed = filename | sed "N;s/\n/\t/"
# 对文件中的所有行编号(行号在左,文字右端对齐)。 sed = filename | sed "N; s/^/     /; s/ *\(.\{6,\}\)\n/\1  /"
# 对文件中的所有行编号,不含空白行。 sed "/./=" filename | sed "/./N; s/\n/ /"
# 对文件中的所有行编号,并加上":" ,含空白行。 sed "/./=" filename |sed "/./N; s/\n/:/"
# 计算行数 (模拟 "wc -l")。 sed -n "$="

文本转换和替代:------

# 替换每一行中的“foo”都换成“bar”。          sed "s/foo/bar/g"
# 替换每一行中的第一个“foo”字串为“bar”。  sed "s/foo/bar/"
# 替换每一行中的第四个“foo”字串为“bar”。    sed "s/foo/bar/4"
# 替换倒数第二个“foo”字串为“bar”。          sed "s/\(.*\)foo\(.*foo\)/\1bar\2/"
# 替换最后一个“foo” 字串为“bar”。           sed "s/\(.*\)foo/\1bar/"
# 只在行中出现字串“baz”的情况下将“foo”替换成“bar”。 sed "/baz/s/foo/bar/g"
# 行中未出现字串“baz”的情况下将“foo”替换成“bar”。 sed "/baz/!s/foo/bar/g"

# 将文本中第1-3行中第三个"a"替换为"b"。     sed "1,3s/a/b/3"
# 将文本中第3-5行中第一、三个"a"替换为"b"。   sed -e "3,5s/a/b/1" -e "3,5s/a/b/3"
# 除了第四行外将所有行的第二个"a"替换为"b"。  sed "4!s/a/b/2"

# 不管是“scarlet”“ruby”还是“puce”,一律换成“red”。sed "s/scarlet/red/g;s/ruby/red/g;s/puce/red/g"

# 将每一行前导的“空白字符”(空格,制表符)删除使之左对齐。 sed "s/^[ \t]*//"
# 将每一行拖尾的“空白字符”(空格,制表符)删除。 sed "s/[ \t]*$//"
# 将每一行中的前导和拖尾的空白字符删除。 sed "s/^[ \t]*//;s/[ \t]*$//"
# 在行首插入字符(含空格)。           sed "s/^/bathome/"
# 在行首插入“header”,在行尾插入“footer”。 sed 's/^\(.*\)$/header\1 footer/'

# 在每一行开头处插入5个空格(使全文向右移动5个字符的位置)。 sed "s/^/     /"
# 以79个字符为宽度,将所有文本右对齐。 sed -e :a -e "s/^.\{1,78\}$/ &/;ta"    # 78个字符外加最后的一个空格
# 以79个字符为宽度,使所有文本居中。在方法1中,为了让文本居中每一行的前头和后头都填充了空格。 在方法2中,在居中文本的过程中只在文本的前面填充空格,并且最终这些空格将有一半会被删除。此外每一行的后头并未填充空格。
sed  -e :a -e "s/^.\{1,77\}$/ & /;ta"                     # 方法1
sed  -e :a -e "s/^.\{1,77\}$/ &/;ta" -e "s/\( *\)\1/\1/"  # 方法2

# 所有以http://开头的行都会被替换成它自已加192.168.0.1,变成http://192.168.0.1localhost。sed "s/^http\:\/\//&192.168.0.1/"   &符号表示替换换字符串中被找到的部份。
# love被标记为1,所有loveable会被替换成lovers,而且替换的行会被打印出来。  sed -n "s/\(love\)able/\1rs/p"
# 不论什么字符,紧跟着s命令的都被认为是新的分隔符,所以,“#”在这里是分隔符,代替了默认的“/”分隔符。表示把所有10替换成100。 sed "s#10#100#g"
# 对于模板test和west之间的行,每行的末尾用字符串sed test替换。 sed "/test/,/check/s/$/sed test/"
# 用"pause"来取代第5------8行所有的内容(非每行)。 sed "5,8c\pause"  c开关是sed中用用户输入内容来取代原本内容的,其后紧跟"\",用这种方法同样可以将指定行替换为空行(并不是严格意义上的空行,至少有一个空格)

# 倒置所有行,第一行成为最后一行,依次类推(模拟“tac”)。由于某些原因,使用下面命令时HHsed v1.5会将文件中的空行删除
sed "1!G;h;$!d"               # 方法1
sed -n "1!G;h;$p"             # 方法2

# 将行中的字符逆序排列,第一个字成为最后一字,……(模拟“rev”)。 sed "/\n/!G;s/\(.\)\(.*\n\)/&\2\1/;//D;s/.//"
# 将文件中包含的字符串(本例为“they”)中的4个字按4132顺序变换(变为yteh)。sed "s/\(t\)\(h\)\(e\)\(y\)/\4\1\3\2/"

# 将每两行连接成一行(类似“paste”)。 sed "$!N;s/\n/ /"
# 如果当前行以反斜杠“\”结束,则将下一行并到当前行末尾并去掉原来行尾的反斜杠。 sed -e :a -e "/\\$/N; s/\\\n//; ta"
# 如果当前行以等号开头,将当前行并到上一行末尾并以单个空格代替原来行头的“=”。 sed -e :a -e "$!N;s/\n=/ /;ta" -e "P;D"

# 为数字字串增加逗号分隔符号,将“1234567”改为“1,234,567”。sed -e :a -e "s/\(.*[0-9]\)\([0-9]\{3\}\)/\1,\2/;ta"  # 其他sed
# 为带有小数点和负号的数值增加逗号分隔符(GNU sed)gsed -r ":a;s/(^|[^0-9.])([0-9]+)([0-9]{3})/\1\2,\3/g;ta"

选择性地显示特定行:------

# 只显示匹配正则表达式的行(模拟“grep”)。sed -n "/regexp/p"  # 方法1  sed "/regexp/!d" # 方法2
# 只显示不包含正则表达式的行。sed -n "/regexp/!p" # 方法1,与前面的命令相对应。sed "/regexp/d"  # 方法2,类似的语法
# 显示匹配或发生的行。sed -n "s/^test/mytest/p"  -n开关是表示输出由编辑指令控制,p开关是有条件显示开关。

# 显示从包含正则表达式的行开始到最后一行结束。 sed -n "/regexp/,$p"
# 显示通篇文档,除了两个正则表达式之间的内容。 sed "/start/,/end/d" 

# 显示两个正则表达式之间的文本(包含)。 sed -n "/start/,/end/p"   # 区分大小写方式
# 显示从第五行开始到第一个包含以test开始的行之间的所有行。sed -n "5,/^test/p"

# 查找“regexp”并将匹配行的上一行显示出来,但并不显示匹配行。 sed -n "/regexp/{g;1!p;};h"
# 查找“regexp”并将匹配行的下一行显示出来,但并不显示匹配行。 sed -n "/regexp/{n;p;}"
# 显示包含“regexp”的行及其前后行,并在第一行之前加上“regexp”所在行的行号 (类似“grep -A1 -B1”)。 sed -n -e "/regexp/{=;x;1!p;g;$!N;p;D;}" -e h

# 显示既包“AAA”“BBB”“CCC”的行(任意次序)。 sed "/AAA/!d; /BBB/!d; /CCC/!d"  # 字串的次序不影响结果
# 显示包含“AAA”、“BBB”和“CCC”的行(固定次序)。 sed "/AAA.*BBB.*CCC/!d"
# 显示包含“AAA”“BBB”“CCC”任一字符串的行 (模拟“egrep”) sed -e "/AAA/b" -e "/BBB/b" -e "/CCC/b" -e d    # 多数sed

# 显示包含“AAA”的段落 (段落间以空行分隔)HHsed v1.5 必须在“x;”后加入“G;”,接下来的3个脚本都是这样。 sed -e "/./{H;$!d;}" -e "x;/AAA/!d;"
# 显示包含“AAA”“BBB”和“CCC”三个字串的段落 (任意次序)。 sed -e "/./{H;$!d;}" -e "x;/AAA/!d;/BBB/!d;/CCC/!d"
# 显示包含“AAA”、“BBB”、“CCC”三者中任一字串的段落 (任意次序)。sed -e "/./{H;$!d;}" -e "x;/AAA/b" -e "/BBB/b" -e "/CCC/b" -e d

# 显示指定行号范围(从第8至第12行,含8和12行)。sed -n "8,12p" # 方法1 sed "8,12!d" # 方法2
# 显示第52行。sed -n "52p"  # 方法1   sed "52!d" # 方法2   sed "52q;d" # 方法3, 处理大文件时更有效率
# 从第3行开始,每7行显示一次   sed -n "3,${p;n;n;n;n;n;n;}"
# 不显示文本中前10行。  sed 1,10d
# 显示文本的奇数行(含空行)。sed -n -e "p" -e "n"  在sed中用n表示奇数行,用p表示偶数行。
# 显示文本的偶数行(含空行)。sed -n -e "n" -e "p"
# 显示3的倍数行。           sed -n "n;n;p" 先用n开关将输出定向到编辑指令,然后输入法3-1个n;最后用显示开关p结尾,也就时说3前的数字的倍数行不显示,只显示3的倍数行。
# 显示文件中的前10行 (模拟“head”的行为)。 sed 10q
# 显示文件中的第一行 (模拟“head -1”命令)。 sed q
# 显示文件中的最后10行 (模拟“tail”)。 sed -e :a -e "$q;N;11,$D;ba"
# 显示文件中的最后2行(模拟“tail -2”命令)。 sed "$!N;$!D"
# 显示文件中的最后一行(模拟“tail -1”)。sed "$!d"   # 方法1 sed -n "$p" # 方法2
# 显示文件中的倒数第二行
sed -e "$!{h;d;}" -e x              # 当文件中只有一行时,输入空行
sed -e "1{$q;}" -e "$!{h;d;}" -e x  # 当文件中只有一行时,显示该行
sed -e "1{$d;}" -e "$!{h;d;}" -e x  # 当文件中只有一行时,不输出

# 显示文本含有数字的行。sed -n "/[0-9]/p"
# 显示文本不含有数字的行。sed "/[0-9]/d"

# 显示包含65个或以上字符的行。 sed -n "/^.\{65\}/p"
# 显示包含65个以下字符的行。sed -n "/^.\{65\}/!p"  # 方法1,与上面的脚本相对应。 sed "/^.\{65\}/d" # 方法2,更简便一点的方法。

选择性地删除特定行:------

# 删除匹配式样的行。 sed "/pattern/d"     # 删除含pattern的行。当然pattern可以换成任何有效的正则表达式
# 删除匹配式样以外的行。 sed "/pattern/!d"

# 删除文件中相邻的重复行(模拟“uniq”)只保留重复行中的第一行,其他行删除。 sed "$!N; /^\(.*\)\n\1$/!P; D"
# 删除文件中的重复行,不管有无相邻。 sed -n "G; s/\n/&&/; /^\([ -~]*\n\).*\n\1/d; s/\n//; h; P"
# 删除除重复行外的所有行(模拟“uniq -d”)。 sed "$!N; s/^\(.*\)\n\1$/\1/; t; D"

# 删除文件中开头的10行。 sed "1,10d"
# 删除文件中的最后一行。 sed "$d"
# 删除example文件的第二行。 sed "2d"
# 删除文件中的最后两行。 sed "N;$!P;$!D;$d"
# 删除文件中的最后10行。sed -e :a -e "$d;N;2,10ba" -e "P;D"   # 方法1  sed -n -e :a -e "1,10!{P;N;D;};N;ba"  # 方法2
# 删除example文件的第二行到末尾所有行。 sed "2,$d" example
# 删除文件中第2行到第一个"write"所在行(含该行)之间的所有内容。 sed "2,/write/d"
# 删除8的倍数行。sed "n;n;n;n;n;n;n;d;"

# 删除文件中的所有空行。sed "/^$/d"  # 方法1  sed "/./!d" # 方法2
# 只保留多个相邻空行的第一行。并且删除文件顶部和尾部的空行。(模拟“cat -s”)
sed "/./,/^$/!d"        #方法1,删除文件顶部的空行,允许尾部保留一空行
sed "/^$/N;/\n$/D"      #方法2,允许顶部保留一空行,尾部不留空行
# 只保留多个相邻空行的前两行。 sed "/^$/N;/\n$/N;//D"
# 删除文件顶部的所有空行。 sed "/./,$!d"
# 删除文件尾部的所有空行。  sed -e :a -e "/^\n*$/{$d;N;ba" -e "}"  # 对所有sed有效

# 删除每个段落的最后一行。 sed -n "/^$/{p;h;};/./{x;/./p;}"

# 删除文本所有行首的四个字符。sed "s/^....//"
# 删除文本所有行尾的四个字符。sed "s/....$//"

多点编辑:e命令 ------
# (-e)选项允许在同一行里执行多条命令。 sed -e "1,5d" -e "s/test/check/"
# 给sed表达式赋值。  sed --expression="s/test/check/" --expression="/love/d" 一个比-e更好的命令是--expression。

从文件读入:r命令 ------
# file里的内容被读进来,显示在与test匹配的行后面。 sed "/test/r file" 如果匹配多行,则file的内容将显示在所有匹配行的下面。

写入文件:w命令 ------
# 在example中所有包含test的行都被写入file里。 sed -n "/test/w file"

追加命令:a命令 ------
# 在所有包含test行的下一行插入“newline”行。sed "/test/a\newline"
# 在文本中每一行下插入“newline”行。        sed "a\newline"

插入:i命令 ------
# 在所有包含test行的上一行插入“newline”行。sed "/test/i\newline"
# 在文本中每一行上面插入“newline”行。      sed "i\newline"

下一个:n命令 ------
# 如果test被匹配,则将下一行中的aa替换为bb,并打印该行。 sed "/test/{ n; s/aa/bb/; }" 注意:如果连续有三行包含test和aa,只有第二行的aa会被替换。

变形:y命令------
将文本中的字母换成大写。sed "y/abcdefg/ABCDEFG/" y开关是sed中真正的变形开关,同理可以将文本中的数字全变成大写数字。
# 把1--10行内所有abcde转变为大写,注意,正则表达式元字符不能使用这个命令。 sed "1,10y/abcde/ABCDE/"

退出:q命令 ------
# 打印完第10行后,退出sed。 sed "10q"

保持和获取:h命令和G命令 ------
# 在sed处理文件的时候,每一行都被保存在一个叫模式空间的临时缓冲区中,除非行被删除或者输出被取消,否则所有被处理的行都将 打印在屏幕上。接着模式空间被清空,并存入新的一行等待处理。在这个例子里,匹配test的行被找到后,将存入模式空间,h命令将其复制并存入一个称为保 持缓存区的特殊缓冲区内。第二条语句的意思是,当到达最后一行后,G命令取出保持缓冲区的行,然后把它放回模式空间中,且追加到现在已经存在于模式空间中 的行的末尾。在这个例子中就是追加到最后一行。简单来说,任何包含test的行都被复制并追加到该文件的末尾。 sed -e "/test/h" -e "$G

保持和互换:h命令和x命令 ------
# 互换模式空间和保持缓冲区的内容。也就是把包含test与check的行互换。  sed -e "/test/h" -e "/check/x" example -----

特殊应用:------
# 移除手册页(man page)中的nroff标记。在Unix System V或bash shell下使用"echo"命令时可能需要加上 -e 选项。
sed "s/.^H//g"             # 在bash或tcsh中, 按 Ctrl-V 再按 Ctrl-H
sed "s/.\x08//g"           # sed 1.5,GNU sed,ssed所使用的十六进制的表示方法
# 提取新闻组或 e-mail 的邮件头。 sed "/^$/q"                # 删除第一行空行后的所有内容
# 提取新闻组或 e-mail 的正文部分。 sed "1,/^$/d"              # 删除第一行空行之前的所有内容
# 从邮件头提取“Subject”(标题栏字段),并移除开头的“Subject:”字样。 sed "/^Subject: */!d; s///;q"
# 从邮件头获得回复地址。 sed "/^Reply-To:/q; /^From:/h; /./d;g;q"
# 获取邮件地址。在上一个脚本所产生的那一行邮件头的基础上进一步的将非电邮地址的部分剃除。(见上一脚本)。 sed "s/ *(.*)//; s/>.*//; s/.*[:<] *//"
# 在每一行开头加上一个尖括号和空格(引用信息)。 sed "s/^/> /"
# 将每一行开头处的尖括号和空格删除(解除引用)。 sed "s/^> //"
# 移除大部分的HTML标签(包括跨行标签)。 sed -e :a -e "s/<[^>[]*>//g;/</N;//ba"
# 将分成多卷的uuencode文件解码。移除文件头信息,只保留uuencode编码部分。文件必须以特定顺序传给sed。下面第一种版本的脚本可以直接在命令行下输入;第二种版本则可以放入一个带执行权限的shell脚本中。(由Rahul Dhesi的一个脚本修改而来。)
sed "/^end/,/^begin/d" file1 file2 ... fileX | uudecode   # vers. 1
sed "/^end/,/^begin/d" "$@" | uudecode                    # vers. 2
# 将文件中的段落以字母顺序排序。段落间以(一行或多行)空行分隔。sed "/./{H;d;};x;s/\n/={NL}=/g" file | sort | sed "1s/={NL}=//;s/={NL}=/\n/g"
# 分别压缩每个.TXT文件,压缩后删除原来的文件并将压缩后的.ZIP文件命名为与原来相同的名字(只是扩展名不同)。(DOS环境:“dir /b”显示不带路径的文件名)。
echo @echo off >zipup.bat
dir /b *.txt | sed "s/^\(.*\)\.TXT/pkzip -mo \1 \1.TXT/" >>zipup.bat

使用SED:Sed接受一个或多个编辑命令,并且每读入一行后就依次应用这些命令。当读入第一行输入后,sed对其应用所有的命令,然后将结果输出。接着再读入第二行输入,对其应用所有的命令……并重复这个过程。上一个例子中sed由标准输入设备(即命令解释器,通常是以管道输入的形式)获得输入。在命令行给出一个或多个文件名作为参数时,这些文件取代标准输入设备成为sed的输入。sed的输出将被送到标准输出(显示器)。因此:

cat filename | sed "10q"         # 使用管道输入
sed "10q" filename               # 同样效果,但不使用管道输入
sed "10q" filename > newfile     # 将输出转移(重定向)到磁盘上

  括号语法:前面的例子对sed命令基本上都使用单引号("...")而非双引号("...")这是因为sed通常是在Unix平台上使用。单引号下,Unix的shell(命令解释器)不会对美元符($)和后引号(`...`)进行解释和执行。而在双引号下美元符会被展开为变量或参数的值,后引号中的命令被执行并以输出的结果代替后引号中的内容。而在“csh”及其衍生的shell中使用感叹号(!)时需要在其前面加上转义用的反斜杠(就像这样:\!)以保证上面所使用的例子能正常运行(包括使用单引号的情况下)。DOS版本的Sed则一律使用双引号("...")而不是引号来圈起命令。

  "\t"的用法:为了使本文保持行文简洁,我们在脚本中使用"\t"来表示一个制表符。但是现在大部分版本的sed还不能识别"\t"的简写方式,因此当在命令行中为脚本输入制表符时,你应该直接按TAB键来输入制表符而不是输入"\t"。下列的工具软件都支持"\t"做为一个正则表达式的字元来表示制表符:awk、perl、HHsed、sedmod以及GNUsed v3.02.80。
脚本
Sed脚本是一个sed的命令清单,启动Sed时以-f选项引导脚本文件名。Sed对于脚本中输入的命令非常挑剔,在命令的末尾不能有任何空白或文本,如果在一行中有多个命令,要用分号分隔。以#开头的行为注释行,且不能跨行。

小技巧
在sed的命令行中引用shell变量时要使用双引号,而不是通常所用的单引号。下面是一个根据name变量的内容来删除named.conf文件中zone段的脚本:

name="zone\ "localhost""sed "/$name/,/};/d" named.conf

###############################################################################################################

1. Sed简介
sed 是一种在线编辑器,它一次处理一行内容。处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”(pattern space),接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。接着处理下一行,这样不断重复,直到文件末尾。文件内容并没有改变,除非你使用重定向存储输出。Sed主要用来自动编辑一个或多个文件;简化对文件的反复操作;编写转换程序等。以下介绍的是Gnu版本的Sed 3.02。

2. 定址
可以通过定址来定位你所希望编辑的行,该地址用数字构成,用逗号分隔的两个行数表示以这两行为起止的行的范围(包括行数表示的那两行)。如1,3表示1,2,3行,美元符号($)表示最后一行。范围可以通过数据,正则表达式或者二者结合的方式确定。

3. Sed命令
调用sed命令有两种形式:
sed [options] "command" file(s)
sed [options] -f scriptfile file(s)

a\  在当前行后面加入一行文本。
b  lable  分支到脚本中带有标记的地方,如果分支不存在则分支到脚本的末尾。
c\  用新的文本改变本行的文本。
d  从模板块(Pattern  space)位置删除行。d开关是表示删除的意思。
D  删除模板块的第一行。
i\  在当前行上面插入文本。
h  拷贝模板块的内容到内存中的缓冲区。
H  追加模板块的内容到内存中的缓冲区
g  获得内存缓冲区的内容,并替代当前模板块中的文本。
G  获得内存缓冲区的内容,并追加到当前模板块文本的后面。
l  列表不能打印字符的清单。
n  读取下一个输入行,用下一个命令处理新的行而不是用第一个命令。
N  追加下一个输入行到模板块后面并在二者间嵌入一个新行,改变当前行号码。
p  打印模板块的行。
P(大写)  打印模板块的第一行。
q  退出Sed。
r  file  从file中读行。
t  label  if分支,从最后一行开始,条件一旦满足或者T,t命令,将导致分支到带有标号的命令处,或者到脚本的末尾。
T  label  错误分支,从最后一行开始,一旦发生错误或者T,t命令,将导致分支到带有标号的命令处,或者到脚本的末尾。
w  file  写并追加模板块到file末尾。
W  file  写并追加模板块的第一行到file末尾。
!  表示后面的命令对所有没有被选定的行发生作用。
s/re/string  用string替换正则表达式re。
=  打印当前行号码。
#  把注释扩展到下一个换行符以前。

以下的是替换标记
g  表示行内全面替换。
p  表示打印行。
w  表示把行写入一个文件。
x  表示互换模板块中的文本和缓冲区中的文本。
y  表示把一个字符翻译为另外的字符(但是不用于正则表达式)

4. 选项
-e  command,  --expression=command  允许多台编辑。
-h,  --help  打印帮助,并显示bug列表的地址。
-n,  --quiet,  --silent  取消默认输出。
-f,  --filer=script-file  引导sed脚本文件名。
-V,  --version  打印版本和版权信息。

5. 元字符集
^  锚定行的开始  如:/^sed/匹配所有以sed开头的行。
$  锚定行的结束  如:/sed$/匹配所有以sed结尾的行。
$p  最后一行
.  匹配一个非换行符的字符  如:/s.d/匹配s后接一个任意字符,然后是d。
*  匹配零或多个字符  如:/*sed/匹配所有模板是一个或多个空格后紧跟sed的行。
[]  匹配一个指定范围内的字符,如/[Ss]ed/匹配sed和Sed。
[^]  匹配一个不在指定范围内的字符,如:/[^A-RT-Z]ed/匹配不包含A-R和T-Z的一个字母开头,紧跟ed的行。
\(..\)  保存匹配的字符,如s/\(love\)able/\1rs,loveable被替换成lovers。
&  保存搜索字符用来替换其他字符,如s/love/**&**/,love这成**love**。
\<  锚定单词的开始,如:/\<love/匹配包含以love开头的单词的行。
\>  锚定单词的结束,如/love\>/匹配包含以love结尾的单词的行。
x\{m\}  重复字符x,m次,如:/0\{5\}/匹配包含5个o的行。
x\{m,\}  重复字符x,至少m次,如:/o\{5,\}/匹配至少有5个o的行。
x\{m,n\}  重复字符x,至少m次,不多于n次,如:/o\{5,10\}/匹配5--10个o的行。

6.执行档案内的编辑指令
当执行的指令太多 , 在命令列上撰写起来十分混乱 , 此时 , 可将这些指令整理储存在档案(譬如档名为 script_file )内 , 用选项 -f script_file , 则让 sed 执行script_file 内的编辑指令。其命令的格示如下 : sed -f script_file 文件档,其中, 执行 script_file 内编辑指令的顺序是由上而下。例如上一节的例子 , 其可改成如下命令: sed -f ysb.scr yel.dat,其中 , ysb.scr 档的内容如下 : 1,10d s/yellow/black/g,另外, 在命令列上可混合使用选项 -e 与 -f , sed 执行指令顺序依然是由命令列的左到右, 如执行至 -f 後档案内的指令 , 则由上而下执行。

7. 执行多个文件档的编辑
在 sed 命令列上 , 一次可执行编辑多个文件档 , 它们跟在编辑指令之後。例如 , 替换white.dat、red.dat、black.dat 档内的 "yellow" 字串成 "blue" , 其命令如下: sed -e 's/yellow/blue/g' white.dat red.dat black.dat,上述命令执行时 , sed 依 white.dat、red.dat、black.dat 顺序 , 执行编辑指令 s/yellow/blue/(请参照[section 4.1] ,进行字串的替换.。

8.执行输出的控制

在命令列上的选项 -n (解[7]) 表示输出由编辑指令控制。由前章内容得知 ,sed 会 "自动的" 将资料由 pattern space 输送到标准输出档。但藉着选项 -n , 可将 sed 这 "自动的" 的动作改成 "被动的" 由它所执行的编辑指令(解[8])来决定结果是否输出。由上述可知 , 选项 -n 必须与编辑指令一起配合 , 否则无法获得结果。
例如 ,印出 white.dat 档内含有 "white"  字串的资料行 , 其命令如下: sed -n -e '/white/p' white.dat
上面命令中 , 选项 -n 与编辑指令 /white/p (参照[section4.6]) 一起配合控制输出。其中 , 选项 -n 将输出控制权移给编辑指;/white/p 将资料行中含有 "white" 字串印出萤幕。

IBM Knowledge Center - sed 命令

sed介绍 - 简书

Sed and awk 笔记之 sed 篇:简单介绍 - 简书

Linux之Sed工具的使用详解 - 简书

sed一句话技巧 « Zhiyan - 段志岩

`