[shell]sed-迁

 

1 命令模式

 

1.1 编辑命令模式

格式 sed [options] 'command' file(s)
command 部分:[地址1,地址2][函数][参数]
1.1.1 一个或两个地址是可以省略的
1.1.2 可以用任何数目的空白或tab把地址和函数分隔开
1.1.3 函数必须出现
1.1.4 依据给出的是哪个函数,标记可能是必需的或者是可选的
1.1.5 引用shell变量时要使用双引号,而不是通常所用的单引号

1.2 脚本模式

格式 sed [options] -f scriptfile files
1.2.1 脚本是一个sed的命令清单
1.2.2 在命令的结尾不能有任何的空白或文本
1.2.3 如果一行中有多个命令,要用分号分隔
1.2.4 不需要且不能用引号保护命令
1.2.5 以#开头的行为注释,且不能跨行

/western/,/southease/{
/^$/d
/Suan/{h;d}
}
/Ann/g
s/TB \(Savage\)/Thomas \1/

 

#去掉空行
sed /^$/d file

   

1.3 options 部分(命令行标志)

-e 下一个参数接受为编辑命令,允许多项编辑

sed -e '1,3d' -e 's/west/north/' file 

注意:

多个命令都在模式空间的当前行上执行

编辑命令的顺序会影响结果

  • -i 直接修改目标文件
  • -f 把下一个参数接受为脚本名,这个文件应当包含一行一个的编辑命令
  • -n 不输出所有行,只复制p函数或在s函数后p标志所指定的行

 

2 多输入行 

  • D 删除当前模式空间中直到并包括第一个换行字符的所有字符
  • N 追加下一个输入行到模式空间后面合并在两者间嵌入一个换行符,改变当前号码模式匹配可以延伸跨越这个内嵌换行
  • P 打印模式空间中的直到并包括第一个换行的所有字符
  • q 结束或退出sed
  • l 列出非打印字符

 

3 定址 

删除第一行,十进制数

sed '1d' file​

  

正则表达式 

sed '/john/d' file #删除包含john的行
sed '/^john/d' file #删除john打头的行   

注意使用特殊字符(^ $ . * [ ]  \ /) 都要用 \ 来转义字符 

 

逗号分隔符

sed '1,3d' file #删除第一行和第三行之间的范围
sed '/west/,/east/d' file #删除west和east之间的行

  

组合方式

sed '1,/west/d' file #第一行开始到west之间的所有行

  

特殊情况

sed '$d' file  #字符 $ 匹配最后一个​

  

sed 特殊格式

sed -n '2p' #只输出第二行
sed -n '0,/west/p' file #从第一行开始匹配到west为止
sed -n '/west/,+2p' file #匹配west后,再操作west后N行
sed -n '/west/,~6' file #匹配west后再操作到N的倍数的行为止
sed -n '0~5p' file #从0行开始每5行操作一次
sed -n '/west\|esat/p' file #匹配模式west和east​

  

4 正则表达式

行首定位符

/^love/

  

行尾定位符

/love$/​

  

匹配除换行符外的单个字符

/l..e/​

  

匹配0个或多个前一字符

/*love/

  

匹配指定字符组内的任一字符

/[Ll]over/​

  

匹配不在指定字符组内的任一字符

匹配包含over,但over之前的那个字符不在 A到K或M到Z之间的行
/[^A-KM-Z]over/ 

  

保存被匹配的字符

最多可以使用9个标签,模式中最左边的标签是第一个,本例:模式love被保存为标签 \1,以后可引用为 \1,
这个例子中,查找字符串是love后面跟着r替换成loveable
echo "my deer lover"|sed 's/\(love\)r/\1able/' 
my deer loveable

取前11个字符,用到了\1的方法和取字符的方法,通awk的substr($1,1,11)
echo -e "! in the west i42\n want to listen the radio\n east use nothing88\n just"|sed -rn 's/^(.{11}).*/\1/p'
! in the we
 want to li
 east use n

  

词首定位

/\<love/

  

词尾定位

 /love\>/​

  

连续m个字符x

匹配连续出现5个o的行 /o\{5\}/   x\{\m}
至少m个的x x\{m,\}
至少m个但不超过n个的x x\{m,n\}

  

5 函数

插入、修改、删除

a\

当前行后添加一或多行  ,a后面第二个反斜杠用来被shell转义为换行符

echo "my deer lover"|sed '/^my/a\\ -->test<--' 
my deer lover
 -->test<--

#35行增加一条数据,并将原文件重命名
sed -i_bak '35 a \mongodb    = 192.168.100.65:50005'  config.ini

#最后一行插入[append]
sed "$ a test" my.txt 

#追加内容
sed -i '/^root.*ALL$/a nagios   ALL=(ALL)   NOPASSWD: ALL' /etc/sud
oers    

#行前加
sed -i '/allow chengyongxu.com/i\allow chengyongxu.cn' the.conf.file
#行前后
4sed -i '/allow chengyongxu.com/a\allow chengyongxu.cn' the.conf.file

  

i\ 

当前行上添加一或多行

第二行插入[insert] 
sed "2 i test" my.txt   

  

d

删除第3行

sed '3d' file

  

匹配到,删除其后3行

sed '/lotterycore-1-1/,+3d' /etc/salt/roster

  

查找替换

匹配到后,整行操作

#修改第28行
sed -i '28 c \fudge   134.98.5.80  stratum 10' /etc/ntp.conf 

#匹配到dog,如果匹配整行到就替换为test000000
sed "/dog/c test000000" my.txt

  

s

匹配到后,只对匹配部分操作

sed 's/west/north/g' file 将west替换成north,后面的g表示全局替换
sed 's#west#north#g' file 使用 "#" 替换默认分隔符"/" ,仅在使用s命令时
sed  "s/$Old_url/$New_url/g"  $salt_dir/yixin_index.js|grep "http" 遇到变量的参数,需要将 ' 改为 " 
'
#匹配到west,后面空格可以用正则表达式处理替换,-n p只打印做操作那行
echo -e "! in the west i42\n want to listen the radio\n east use nothing88\n just"|sed -n 's/west\+.i/123\ /p'
! in the 123 42

sed  's/west/[&]/'  #只对匹配到west做修改
! in the [west] i42

去掉 ^M
^M是使用 "CTRL-V CTRL-M"
sed -e "s/^V^M//"  或者 %s/^M//g

利用for和grep -v反向匹配,循环sed
注意,遇到中文字符sed会卡住!
for i in `ls|grep -v ^img`;do echo $i; sed -i 's/\.+/\\S+/' $i;done

  

多次匹配用; 号隔开

sed -i "s/1-1.salt/10.4.230.2/;s/10.4.234.1/10.4.230.2/ 

  

先匹配再对整行修改替换

#匹配在west和east之间,行的最后替换为**vava**
echo -e "! in the west i\n want to listen the radio\n east use nothing\n just"|sed '/west/,/east/s/$/**vava**/'
! in the west i**vava**
 want to listen the radio**vava**
 east use nothing**vava**
 just
 
# 匹配到west然后头加#
sed /west/'s/^/# /'
# ! in the west i42

 
#匹配到west后行尾加@ecp
sed  /west/'s/.*/&@ecp/'
! in the west i42@ecp

#匹配到west后行首加@ecp
sed  /west/'s/X*/&@ecp/'
@ecp! in the west i42

  

 所有以两位数字结尾的行后面都被加上.5,怎么变成两行了??

echo -e "! in the west i42\n want to listen the radio\n east use nothing88\n just"|sed 's/[0-9][0-9]$/&444/p'
! in the west i42444
! in the west i42444
 want to listen the radio
 east use nothing88444
 east use nothing88444
 just

  

匹配到后修改本行及其后两行

echo -e "! in the west i42\n want to listen the radio\n east use nothing88\n just"|sed '/west/,+2s/^/# /g'
# ! in the west i42
#  want to listen the radio
#  east use nothing88
 just

  

保存和取回

hold space  == 暂存空间

pattern space == 模式空间

 

h: 将pattern space中的内容拷贝到hold space中,原来的hold space里的内容被清除

匹配到west的行,放入暂存区(只保留最后一次操作),然后追加到文件的最后
echo -e "! in the west i42\n want to listen the radio\n east use nothing88\n just"|sed -e '/west/h' -e '$G'
! in the west i42
 want to listen the radio
 east use nothing88
 just
! in the west i42

  

H: 将pattern space中的内容append到hold space\n后

匹配到west的行,放入暂存区,然后追加到文件的最后
$ echo -e "! in the west i42\n want to listen the radio\n east use nothing88\n just"|sed -e '/west/H' -e '$G'
! in the west i42
 want to listen the radio
 east use nothing88
 just

! in the west i42

  

g: 将hold space中的内容拷贝到pattern space中,原来pattern space里的内容清除

匹配到east,把east拷贝到模式空间然后删掉,匹配所有west行,删掉
echo -e "! in the west i42\n want to listen the radio\n east use nothing88\n just"|sed -e '/east/{h;d;}' -e '/west/{g;}'

 want to listen the radio
 just
 

  

G: 将hold space中的内容append到pattern space\n后

匹配到west的行,会被拷贝到暂存空间,并删除,然后被追加到文件的最后一行
$ echo -e "! in the west i42\n want to listen the radio\n east use nothing88\n just"|sed -e '/west/{h;d}' -e '$G'
 want to listen the radio
 east use nothing88
 just
! in the west i42

  

x: 交换pattern space和hold space的内容

包含east的行,会被west这行替换掉
echo -e "! in the west i42\n want to listen the radio\n east use nothing88\n just"|sed -e '/west/h' -e '/east/x'
! in the west i42
 want to listen the radio
! in the west i42
 just

  

经典的是将文件格式进行整理

举例:

$ cat /tmp/1
  1-line
  2-line
  3-line

$ sed '2,$G;h;$!d' /tmp/1
  3-line
  2-line
  1-line
 
$ echo -e "! in the west i42\n want to listen the radio\n east use nothing88\n just"|sed -e '2,$G' -e 'h' -e '$!d' just
 east use nothing88
 want to listen the radio
! in the west i42

  

扫描到第一行

  1. 将1-line放入pattern space;此时pattern space还是1-line;
  2. 直接执行h命令,此时hold space是1-line;
  3. 执行d命令,删除了pattern space仅有的一行数据,删除之后,pattern space是空的

    

扫描到第二行

  1. 将2-line放入pattern space
  2. 执行G命令,将hold space的1-line添加到pattern space的2-line的后面,此时pattern space是2-line\n1-line;
  3. 执行h命令,此时hold space的内容是2-line\n1-line;
  4. 执行d命令,pattern space被清空

 

扫描到第三行

  1. 将3-line放入pattern space,
  2. 执行G命令,将hold space的2-line\n1-line添加到pattern space的3-line的后面,此时pattern space是3-line\n2-line\n1-line;
  3. 执行h命令,此时hold space的内容是3-line\n2-line\n1-line;
  4. $!d 到结尾不执行清空操作;

 

直接输出 3-line\n2-line\n1-line

2,$G:从第二行到最后一行执行G命令
h:执行h命令
$!d:删除除了最后一行的所有行 

  

 

输入输出

p 打印行

sed -n '/west/p' file 只打印匹配west的行
sed -n '/west/,/east/p' file 打印模式west和east之间的所有行
sed -n '5/east/p' file 打印5到east之间的行

  

r 从文件中读取输入行

匹配到east,然后输入文件FileRecv/id_rsa.pub
echo -e "! in the west i42\n want to listen the radio\n east use nothing88\n just"|sed  '/east/r FileRecv/id_rsa.pub'
! in the west i42
 want to listen the radio
 east use nothing88
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDNPbxNWoQdIGH1eQnwC+1wY6CXronVyrnkPtFH10
 just

  

w 将行写入文件

匹配到east然后把这行写入到文件
echo -e "! in the west i42\n want to listen the radio\n east use nothing88\n just"|sed  '/east/w /tmp/myfile'
! in the west i42
 want to listen the radio
 east use nothing88
 just

richard@richard-PC:~$ cat /tmp/myfile
 east use nothing88

  

 

控制流

!对所选行以外的所有行应用命令

只保留包含john的行
sed -n '/john/!d' file 

  

{} 组合命令

一组命令作为一个块而被应用

函数命令之间用分号分割

组合可以嵌套

删除west到east之间行,然后把Suan那行保存到暂存模式,然后参数
sed -n '/west/,/east/{/^*/d;/Suan/{h;d;}}' 

  

n 读入下一输行,并从下一条命令,而不是第一条命令开始对其 

echo -e "! in the west i42\n want to listen the radio\n east use nothing88\n just"|sed '/west/{n;s/want/bye/;}'
! in the west i42
 bye to listen the radio
 east use nothing88
 just

  

函数列表

函数参数    功能
:label 建立脚本内指令跳转的参考位置
# 添加注释
{} 集合有相同地址参数的命令
! 不执行函数参数
= 印出资料行数
a\ 添加使用者输入的数据
b label 将执行的指令跳转至:label
c\ 以使用者输入的数据取代数据
d 删除数据
D 删除pattern space内第一个neweline字母\前的数据
g 拷贝数据从hold space
G 添加资料,从hold space到pattern space
h 拷贝资料,从pattern space到hold space
H 添加资料,从pattern space到hold space
l 用ASCII码印出1资料中nonprinting character
i\ 插入添加使用者输入的数据行
n 读取下一笔资料
N 添加下一笔资料到pattern space
p 打印资料
P 打印pattern space内第一个newline 字母\前的数据
q 跳出sed编辑
r 读入文档内容
s 替换字符串
t label 先执行一替换的编辑指令,如果替换成p>,则将编辑指令跳转至:label处执行
w 往文档内写入资料
x 交互hold space和pattern space内容
y 转换(transform)字符

 

echo -e "! in the west i42\n want to listen the radio\n east use nothing88\n just"|python sedsed -d --hide=hold ':f;N;/radio/!bf;s/\n/\ /g'

 

函数解析

将radio结尾的行,上提到上面行尾

PATT:! in the west i42$
COMM::f
COMM:N
PATT:! in the west i42\n want to listen the radio$
COMM:/radio/ !b f
COMM:s/\n/\ /g
PATT:! in the west i42  want to listen the radio$
! in the west i42  want to listen the radio
PATT: east use nothing88$
COMM::f
COMM:N
PATT: east use nothing88\n just$
COMM:/radio/ !b f
COMM:N
 east use nothing88
 just

  

sed ':a;N;/success/!ba;s/\n/\ /g' test  

以success为终点,读取处理文件块,然后再将换行改为空格

 

 

 

 

posted @ 2019-11-15 14:16  richardzgt  阅读(192)  评论(0)    收藏  举报