Linux sed 批量替换字符串方法

将nginx.conf中

 log_format main '[$time_local] $remote_addr $status $request_time $upstream_response_time $request_body'

'$body_bytes_sent "$request" "$http_referer" $upstream_addr'

'$http_x_real_ip $http_x_forwarded_for $http_user_agent $request_filename';


修改为

 log_format main '[$time_local] $remote_addr $status $request $request_time '

                 '$body_bytes_sent "$http_referer" $upstream_addr '

                 '$http_x_real_ip $http_x_forwarded_for $http_user_agent $request_filename ';


命令为:

sed -e '/log_format/{N;N;/.*\;$/s/.*/ log_format main '\''[\$time_local] \$remote_addr \$status \$request \$request_time '\''\n                 '\''\$body_bytes_sent "\$http_referer" \$upstream_addr '\''\n                 '\''\$http_x_real_ip \$http_x_forwarded_for \$http_user_agent \$request_filename '\'';/}' nginx.conf 


首先找到log_format,然后N;N;表示往下对2行,.*\;$表示找到以;符号结尾,s/.*/ log_format main '\''[\$time_local] \$remote_addr \$status \$request \$request_time '\''\n                 '\''\$body_bytes_sent "\$http_referer" \$upstream_addr '\''\n                 '\''\$http_x_real_ip \$http_x_forwarded_for \$http_user_agent \$request_filename '\'';/

表示将匹配的3行内容全部替换为我们想要的内容。


将/data/other/nginx_logs/group.abc.cn_access.log main;替换为
/data/other/nginx_logs/${host}_${server_port}_access.log main;
grep access *|grep -v "#"|sed -e 's%\(/data/other/nginx_logs/\)\(.*\)\(_access.log main;\)%\1${host}_${server_port}\3%g'

意思为,将/data/other/nginx_logs/group.abc.cn_access.log分为3段,一个()表示一段,

/data/other/nginx_logs/为第一段,_access.log main;为第三段,中间的为第二段,然后后面的1和3分别前面的1和3段。

sed 取反(注释行的不替换,!放到后面,好奇怪) sed -e '/#/!s%access_log .*;%access_log /data/other/nginx_logs/${host}_${server_port}_access.log main%g' /usr/local/nginx/conf/vhosts/vhost.conf


检查nginx配置文件有没有哪个虚拟主机没有开启日志

egrep 'server_name|access_log' test.conf|grep -v  "#"|grep -v "\$server_name"|sed -n '/server_name/{$!N;/access_log/!P;D}'

$!表示非最后一行,因为最后一行无需执行下面的命令

匹配到server_name,然后N;表示继续执行查找access_log,/access_log/!P;D,表示如果没有找到access_log,P表示打印出来;D表示删除改行

sed -n '/server_name/{$!N;/access_log/!P;D}'整体意思就是,查到server_name并且不是最后一行的就往下读取一行,如果不匹配access_log就打印出来。


sed -i '/^1.1.1.1.*123.xxx.com$/s//2.2.2.2\t123.xxx.com/g' /etc/hosts


将/etc/hosts中1.1.1.1  123.xxx.com,替换为2.2.2.2  123.xxx.com

s//2.2.2.2\t123.xxx.com/g 表示将匹配的全部替换为后面的内容。

调用sed命令有两种形式:

  • sed [options] 'command' file(s)

  • sed [options] -f scriptfile file(s)

  • a\

  • 在当前行后面加入一行文本。

  • b lable

  • 分支到脚本中带有标记的地方,如果分支不存在则分支到脚本的末尾。

  • c\

  • 用新的文本改变本行的文本。

  • d

  • 从模板块(Pattern space)位置删除行。

  • 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。

  • =

  • 打印当前行号码。

  • #

  • 把注释扩展到下一个换行符以前。



P:Print up to the first embedded newline of the current pattern space.
(就是输出模式空间开头到第一个\n之间的内容)

D:If pattern space contains no newline, start a normal new cycle as if the d command was issued. Otherwise, delete text in the pattern space up to the first newline, and restart cycle with the resultant pattern space, without reading a new line of input.
(是删除模式空间开头到第一个\n(含)之间的内容,并且控制流跳到脚本的第一条语句。这里一定要注意这句话“and restart cycle with the resultant pattern space, without reading a new line of input.”,即它是在不改变当前行号的情况下,从头执行的。)
这句话也充分的说明了,为什么很多人不愿意读中文翻译版书籍的原因。:-)

N:Add a newline to the pattern space, then append the next line of input to the pattern space. If there is no more input then sed exits without processing any more commands.
(追加下一个输入行到模板块后面并在二者间嵌入一个新行,改变当前行号码。如果没有下一个可处理的行,则退出)

以下的是替换标记

  • g表示行内全面替换。

  • p表示打印行。

  • w表示把行写入一个文件。

  • x表示互换模板块中的文本和缓冲区中的文本。

  • y表示把一个字符翻译为另外的字符(但是不用于正则表达式)


4. 选项

  • -e command, --command< /span>

  • 允许多台编辑。

  • -h, --help

  • 打印帮助,并显示bug列表的地址。

  • -n, --quiet, --silent

  • 取消默认输出。

  • -f, --filer=script-file

  • 引导sed脚本文件名。

  • -V, --version

  • 打印版本和版权信息。

5. 元字符集

  • ^

  • 锚定行的开始 如:/^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**。

  • \<

  • 锚定单词的开始,如:/\<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的行。


比如,要将目录/modules下面所有文件中的zhangsan都修改成lisi,这样做:sed -i "s/zhangsan/lisi/g" `grep zhangsan -rl /modules`

解释一下:
-i 表示inplace edit,就地修改文件
-r 表示搜索子目录
-l 表示输出匹配的文件名


这个命令组合很强大,要注意备份文件。

(1)sed 'y/1234567890/ABCDEFGHIJ/' test_sed
sed 'y/1234567890/ABCDEFGHIJ/' filename
ABCDEFGHIJ
BCDEFGHIJA
CDEFGHIJAB
DEFGHIJABC
注意变换关系是按两个list的位置对应变换

其中:test_sed的内容是:
1234567890
2345678901
3456789012
4567890123
(2)
替换每行所有匹配
sed 's/01/Ab/g' test_sed
1234567890
23456789Ab
3456789Ab2
456789Ab23

注意:第一行的0,1没有分别替换为A,b

删除:d命令

  • $ sed '2d' example-----删除example文件的第二行。

  • $ sed '2,$d' example-----删除example文件的第二行到末尾所有行。

  • $ sed '$d' example-----删除example文件的最后一行。

  • $ sed '/test/'d example-----删除example文件所有包含test的行。

因此我们可以这样注释配置文件中的注释行:sed '/#/'d httpd.conf >> httpd1.conf替换:s命令

  • $ sed 's/test/mytest/g' example-----在整行范围内把test替换为mytest。如果没有g标记,则只有每行第一个匹配的test被替换成mytest。

  • $ sed -n 's/^test/mytest/p' example-----(-n)选项和p标志一起使用表示只打印那些发生替换的行。也就是说,如果某一行开头的test被替换成mytest,就打印它。

  • $ sed 's/^192.168.0.1/&localhost/' example-----&符号表示替换换字符串中被找到的部份。所有以192.168.0.1开头的行都会被替换成它自已加 localhost,变成192.168.0.1localhost。

  • $ sed -n 's/\(love\)able/\1rs/p' example-----love被标记为1,所有loveable会被替换成lovers,而且替换的行会被打印出来。

  • $ sed 's#10#100#g' example-----不论什么字符,紧跟着s命令的都被认为是新的分隔符,所以,“#”在这里是分隔符,代替了默认的“/”分隔符。表示把所有10替换成100。


选定行的范围:逗号

  • $ sed -n '/test/,/check/p' example-----所有在模板test和check所确定的范围内的行都被打印。

  • $ sed -n '5,/^test/p' example-----打印从第五行开始到第一个包含以test开始的行之间的所有行。

  • $ sed '/test/,/check/s/$/sed test/' example-----对于模板test和west之间的行,每行的末尾用字符串sed test替换。


多点编辑:e命令

  • $ sed -e '1,5d' -e 's/test/check/' example-----(-e)选项允许在同一行里执行多条命令。如例子所示,第一条命令删除1至5行,第二条命令用check替换test。命令的执 行顺序对结果有影响。如果两个命令都是替换命令,那么第一个替换命令将影响第二个替换命令的结果。

  • $ sed --expression='s/test/check/' --expression='/love/d' example-----一个比-e更好的命令是--expression。它能给sed表达式赋值。


从文件读入:r命令

  • $ sed '/test/r file' example-----file里的内容被读进来,显示在与test匹配的行后面,如果匹配多行,则file的内容将显示在所有匹配行的下面。


写入文件:w命令

  • $ sed -n '/test/w file' example-----在example中所有包含test的行都被写入file里。


追加命令:a命令

  • $ sed '/^test/a\\--->this is a example' example<-----'this is a example'被追加到以test开头的行后面,sed要求命令a后面有一个反斜杠。


插入:i命令 $ sed '/test/i\\
new line
-------------------------' example
如果test被匹配,则把反斜杠后面的文本插入到匹配行的前面。
下一个:n命令

  • $ sed '/test/{ n; s/aa/bb/; }' example-----如果test被匹配,则移动到匹配行的下一行,替换这一行的aa,变为bb,并打印该行,然后继续。


变形:y命令

  • $ sed '1,10y/abcde/ABCDE/' example-----把1--10行内所有abcde转变为大写,注意,正则表达式元字符不能使用这个命令。


退出:q命令

  • $ sed '10q' example-----打印完第10行后,退出sed。


保持和获取:h命令和G命令

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


保持和互换:h命令和x命令

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


7. 脚本

Sed脚本是一个sed的命令清单,启动Sed时以-f选项引导脚本文件名。Sed对于脚本中输入的命令非常挑剔,在命令的末尾不能有任何空白或文本,如果在一行中有多个命令,要用分号分隔。以#开头的行为注释行,且不能跨行。

8. 小技巧

  • 在sed的命令行中引用shell变量时要使用双引号,而不是通常所用的单引号。下面是一个根据name变量的内容来删除named.conf文件中zone段的脚本:
    name='zone\ "localhost"'
    sed "/$name/,/};/d" named.conf


sed -i "s/oldstring/newstring/g" `grep oldstring -rl yourdir`

例如:替换/home下所有文件中的www.itbbs.cn为chinafar.com

sed -i "s/www.itbbs.cn/chinafar.com/g" `grep www.itbbs.cn -rl /home` 二、下面这条命令:
perl -pi -e 's|ABCD|Linux|g' `find ./ -type f`
将调用perl执行一条替换命令,把find命令找到的所有文件内容中的ABCD替换为Linux

find ./ -type f
此命令是显示当前目录下所有的文件

上面的“s|ABCD|Linux| g”是perl要执行的脚本,即把所有ABCD替换为Linux
如果不写最后的那个g,“s|ABCD|Linux| ”将只替换每一行开头的ABCD


当编辑指令(参照[section2.2])在命令列上执行时,其前必须加上选项-e。其命令格式如下:

sed-e'编辑指令1'-e'编辑指令2'...文件档

其中,所有编辑指令都紧接在选项-e之後,并置於两个"'"特殊字元间。另外,命令上编辑指令的执行是由

左而右。

一般编辑指令不多时,使用者通常直接在命令上执行它们。例如,删除yel.dat内1至10行资料,并将其

馀文字中的"yellow"字串改成"black"字串。此时,可将编辑指令直接在命令上执行,其命令如下:

sed-e'1,10d'-e's/yellow/black/g'yel.dat

在命令中,编辑指令'1,10d'(解[5])执行删除1至10行资料;编辑指令's/yellow/black/g'(解[6]),

"yellow"字串替换(substuite)成"black"字串。

2.2sed的编辑指令

sed编辑指令的格式如下:

[address1[,address2]]function[argument]

其中,位址参数address1、address2为行数或regularexpression字串,表示所执行编辑的资料行;函数参

数function[argument]为sed的内定函数,表示执行的编辑动作。

下面两小节,将仔细介绍位址参数的表示法与有哪些函数参数供选择。

2.2.1位址(address)参数的表示法

实际上,位址参数表示法只是将要编辑的资料行,用它们的行数或其中的字串来代替表示它们。下面举几个例子

说明(指令都以函数参数d(参照[section4.2])为例):

删除档内第10行资料,则指令为10d。

删除含有"man"字串的资料行时,则指令为/man/d。

删除档内第10行到第200行资料,则指令为10,200d。

删除档内第10行到含"man"字串的资料行,则指令为10,/man/d。

接下来,以位址参数的内容与其个数两点,完整说明指令中位址参数的表示法(同样也以函数参数d为例)。

位址参数的内容:

位址为十进位数字:此数字表示行数。当指令执行时,将对符合此行数的资料执行函数参数指示的编辑动作。例如,

删除资料档中的第15行资料,则指令为15d(参照[section4.2])。其馀类推,如删除资料档中的第m行资料,则

指令为md。

位址为regularexpression(参照[附录A]):

当资料行中有符合regularexpression所表示的字串时,则执行函数参数指示的编辑动作。另外,在

regularexpression前後必须加上"/"。例如指令为/t.*t/d,表示删除所有含两"t"字母的资料行。其中,"."

表示任意字元;"*"表示其前字元可重任意次,它们结合".*"表示两"t"字母间的任意字串。

位址参数的个数:在指令中,当没有位址参数时,表示全部资料行执行函数参数所指示的编辑动作;当只有一位址

参数时,表示只有符合位址的资料行才编辑;当有两个位址参数,如address1,address2时,表示对资料区执行

编辑,address1代表起始资料行,address2代表结束资料行。对於上述内容,以下面例子做具说明。

例如指令为

d

其表示删除档内所有资料行。

例如指令为

5d

其表示删除档内第五行资料。

例如指令为

1,/apple/d

其表示删除资料区,由档内第一行至内有"apple"字串的资料行。

例如指令为

/apple/,/orange/d

其表示删除资料区,由档内含有"apple"字串至含有"orange"字串的资料行

2.2.2有那些函数(function)参数

下页表中介绍所有sed的函数参数(参照[chapter4])的功能。

函数参数功能

:label建立scriptfile内指令互相参考的位置。转自:
http://blog.chinaunix.net/space.php?uid=715007&do=blog&id=2068617

创建脚本文件a p p e n d . s e d:
第一行是s e d命令解释行。脚本在这一行查找s e d以运行命令,这里定位在/ b i n。
第二行以/ c o m p a n y /开始,这是附加操作起始位置。a \通知s e d这是一个附加操作,首先应插入一个新行。
第三行是附加操作要加入到拷贝的实际文本。
输出显示附加结果。如果要保存输出,重定向到一个文件。

  1. [sam@chenwy sam]$ cat append.sed

  2. #!/bin/sed -f

  3. /company/ a\

  4. Then suddenly it happed.

复制代码

保存它,增加可执行权限,运行

  1. [sam@chenwy sam]chmod u+x append.sed

  2. [sam@chenwy sam]$ ./append.sed quote.txt


复制代码

或直接用命令行:

  1. [sam@chenwy sam]$ sed "/company/a\Then suddenly it happened." quote.txt

[sam@chenwy sam]$ sed "/company/i\utter confusion followed." quote.txt
插入文本:
插入命令类似于附加命令,只是在指定行前面插入。和附加命令一样,它也只接受一个地址。
如在a t t e n d a n c e结尾的行前插入文本utter confusion followed。

  1. [sam@chenwy sam]$ sed "/company/i\Utter confusion followed." quote.txt

复制代码

修改文本
修改命令将在匹配模式空间的指定行用新文本加以替代,格式如下:
将第一行The honeysuckle band played all night long for only $90替换为The office Di b b l e band played well。首先要匹配第一行的任何部分,可使用模式
‘ / H o n e y s u c k l e /’。s e d脚本文件为c h a n g e . s e d。内容如下:


最后去除行尾^ M符号,为此需做全局替换。设置替换部分为空。模式为:
‘s / ^ m / / g’,注意‘^ M’,这是一个控制字符。
在命令行里也必须用^M控制字符耶!?

  1. [sam@chenwy sam]$ sed 's/##/ /g;s/^0*/ /g;s/^M/ /g' dos.txt

  2. 12332 DISO 45.12

  3. 332 LPSO 23.14

  4. 1299 USPD 34.46

复制代码

或[sam@chenwy sam]$ cat dos.txt | sed 's/^0*/ /g' | sed 's/^M/ /g' | sed 's/##/ /g'

任务是在每一行末尾加一个字符串‘ p a s s e d’。
使用$命令修改各域会使工作相对容易些。首先需要匹配至少两个或更多的数字重复出现,这样将所有的帐号加进匹配模式。


  1. [sam@chenwy sam]$ sed 's/[0-9][0-9]*/& Passed/g' ok.txt

  2. AC456 Passed

  3. AC492169 Passed

  4. AC9967 Passed

  5. AC88345 Passed

复制代码


从shell向sed传值
要从命令行中向s e d传值,值得注意的是用双引号,否则功能不执行。


  1. [sam@chenwy sam]$ NAME="It's a go situation"

  2. [sam@chenwy sam]$ REPLACE="GO"

  3. [sam@chenwy sam]$ echo $NAME | sed "s/go/$REPLACE/g"

  4. It's a GO situation

复制代码


从sed输出中设置shell变量
从s e d输出中设置s h e l l变量是一个简单的替换过程。运用上面的例子,创建s h e l l变量N E W- N A M E,保存上述s e d例子的输出结果。


  1. [sam@chenwy sam]$ NAME="It's a go situation"

  2. [sam@chenwy sam]$ REPLACE="GO"

  3. [sam@chenwy sam]$ NEW_NAME=`echo $NAME | sed "s/go/$REPLACE/g"`

  4. [sam@chenwy sam]$ echo $NEW_NAME

  5. It's a GO situation

复制代码


这里的`是键盘左上角那个`

下面是一些一行命令集。([ ]表示空格, [ ]表示t a b键)

‘s / \ . $ / / g’ 删除以句点结尾行
‘-e /abcd/d’ 删除包含a b c d的行
‘s / [ ] [ ] [ ] * / [ ] / g’ 删除一个以上空格,用一个空格代替
‘s / ^ [ ] [ ] * / / g’ 删除行首空格,Deven:这里为什么是2个[ ]呢,纳闷了
‘s / \ . [ ] [ ] * / [ ] / g’ 删除句点后跟两个或更多空格,代之以一个空格
‘/ ^ $ / d’ 删除空行
‘s / ^ . / / g’ 删除第一个字符
‘s /CO L \ ( . . . \ ) / / g’ 删除紧跟C O L的后三个字母
‘s / ^ \ / / / g’ 从路径中删除第一个\
‘s / [ ] / [ ] / / g’ 删除所有空格并用t a b键替代
‘S / ^ [ ] / / g’ 删除行首所有t a b键
‘s / [ ] * / / g’ 删除所有t a b键

3. 删除首字符
s e d删除字符串“a c c o u n t s . d o c”首字符。

echo "accounts.doc" |sed 's/^.//g'

参考:http://www.cnblogs.com/fhefh/archive/2011/11/22/2259097.html


sed之G、H、g、h使用

什么是sed?

sed是面向流的行编辑器,所谓面向流,是指接受标准输入的输入,输出内容到标准输出上。

sed如何处理数据?

sed在正常情况下,将处理的行读入模式空间(pattern space),脚本中的“sed-command(sed命令)”就一条接着一条进行处理,知道脚本执行完毕。然后该行呗输出,模式(pattern space)被清空;接着,在重复执行刚才的动作,文件中的新的一行被读入,直到文件处理完毕。

111802690.png


什么是Pattern Space,什么是Hold Space?

pattern space相当于车间sed把流内容在这里处理。

hold space相当于仓库,加工的半成品在这里临时储存。

PS:你可以将pattern space看成是一个流水线,所有的动作都是在“流水线”上执行的;而hold space是一个“仓库”,“流水线”上的东东都可以放到这里。

为什么要使用sed高级命令(G、H、g、h、n、N、x)?

由于各种各样的原因,比如用户希望在某个条件下脚本中的某个命令被执行,或者希望模式空间得到保留以便下一次的处理,都有可能使得sed在处理文件的时候不按照正常的流程来进行。这个时候,sed设置了一些高级命令来满足用户的要求。

sed命令:

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

+ G:[address[,address]]G 将hold space中的内容append到pattern space\n后

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

+ H:[address[,address]]H 将pattern space中的内容append到hold space\n后

+ d:[address[,address]]d 删除pattern中的所有行,并读入下一新行到pattern中

+ D:[address[,address]]D 删除multiline pattern中的第一行,不读入下一行

PS:不论是使用G、g还是H、h,它们都是将hold space里面的内容“copy”到pattern space中或者将pattern space中的内容“copy”到hold space中。

附上英文的解释(注意其中的高亮单词):

The "h" command copies the pattern buffer into the hold buffer. The pattern buffer is unchanged.

Instead of exchanging the hold space with the pattern space, you can copy the hold space to the pattern space with the "g" command. This deletes the pattern space. If you want to append to the pattern space, use the "G" command. This adds a new line to the pattern space, and copies the hold space after the new line.


示例:用sed模拟出tac的功能(倒序输出)。

文件内容

cat mm

1

2

3

解决方法:

?

sed ‘1!G;h;$!d’mm

ps:1!G第1行不 执行“G”命令,从第2行开始执行。

   $!d,最后一行不删除(保留最后1行)

图解分析过程,注意是每行都要执行:1!G;h;$!d

P:Pattern Space

H:Hold Space

蓝色:Hold Space中的数据

绿色:Pattern Space中的数据

111903688.png


SED 常用command

p (sed �Cn)
显示行
=
显示行号
=在这里是command
g
加空行
d
删除行
/pattern/s/原串/替换串  
sed '/disable/s/yes/no/g'

s/\n//
s/aaa/aaabbb/或s/aaa/&bbb
s/aaa//

替换
把含有disable的行中所有(g)的yes换成no

‘回车’换成‘空’,删除回车符,提行,合行
行内aaa后插入词bbb
行内删除词------就是”空词//”替换
/zzz/a \xxx\yyy

/zzz/a \\

/zzz/a \\yyy
在匹配行zzz,行内xxx后追加yyy

在匹配行zzz,另起一行追加空行

在匹配行zzz,另起一行追加yyy
/pattern/r 22.txt' 111.txt 从文件22.txt读出,然后追加到111.txt





Sed 最基本的sed �Cn ‘p’功能=grep的功能

sed -n '/disable/p' 111.txt
grep disable 111.txt
sed -n '/disable/!p' 111.txt grep -v disable 111.txt



sed �Cn‘=’ 表示”显示行号,但不显示行内容

[macg@machome ~]$ sed -n '=' 111.txt
1
2
3
4
[macg@machome ~]$ sed -n '/disable/=' 111.txt
查找文件中含有disable的行的行号
3
9



Sed ‘=’ file和sed �Cn ‘=’ file的区别

Sed �Cn ‘=’ 1.txt
只显示行号
sed = 1.txt
显示行号,同时显示每行内容(没有-n)



/pattern/s/原串/替换串查找并替换

# more 111.txt
this is 111file
this is 222file
disable = yes
this is file
test1 = yes
test2 = yes
[root@machome macg]#  sed'/disable/s/yes/no/g' 111.txt
this is 111file
this is 222file
disable = no
this is file
test1 = yes
test2 = yes
  • 常见的用法是把/pattern/省略,即针对所有行,直接s打头――s/xxx/yyy/

#  sed 's/yes/no/' 111.txt
this is 111file
this is 222file
disable = no
this is file
test1 = no
test2 = no


s/xxx/yyy缺陷:替换每行只进行一次就停止,若要全部替换,要加参数g,s/xxx/yyy/g

$ sed s/echo/test/ ttt1
test  echo  echo
标准替换s
只替换每一行中的第一个“echo”字串
$ sed s/echo/test/g ttt1
test test  test
全部替换s/xxx/yyy/g
将每一行中的所有的echo都换成“test”



替换s,别忘了尾部的/
$ sed s/echo/test ttt1
sed: -e expression_r_r #1, char 11: unterminated `s' command
$ sed s/echo/test/ ttt1


!s 不匹配的行,替换(不匹配,!加在comand上而不是pattern上)
sed '/baz/!s/foo/bar/g' !s加/pattern/
不含有/pattern/的行替换

; 多重替换 (实际就是多语句,只不过用;加在一行里)
sed 's/scarlet/red/g;s/ruby/red/g;s/puce/red/g'
不管是“scarlet”“ruby”还是“puce”,一律换成“red”


s/\n//  ‘回车’换成‘空’,删除回车符,提行,合行


/pattern/a\xxx\yyy 在匹配pattern的行的xxx后面追加yyy
实际等于两个匹配条件:

  • 第一个匹配条件确定行

  • 第二个匹配条件确定行内的追加位置

sed"${LINENO}a\ FontPath \"/usr/share/fonts/ttf/zh_CN/\""


/pattern/a\\yyy 行尾追加(另起一行追加)更常用些
匹配pattern行,并且另起一行追加yyy

[macg@machome ~]$ sed '/^disable/a\\this is a test' 111.txt
将a\\后的内容追加到disable打头的行后面行(另起一行

this is 111file
this is 222file
disable =yes
本行是空格打头,不是disable打头,所以不匹配^disable

this is 333file
this is 444file
this is file
test1 = yes
test2 = yes
disable=no
this is atest
[macg@machome ~]$ sed '/disable/a\\this is a test'111.txt
将a\\后的内容追加到含有disable的行后面行(另起一行)

this is 111file
this is 222file
disable = yes
this is atest
this is 333file
this is 444file
this is file
test1 = yes
test2 = yes
disable=no
this is atest



Sed‘3a\\yyy’ 匹配行号并追加

[macg@machome ~]$ sed '3a\\ this is a test' 111.txt
this is 111file
this is 222file
disable = yes
this is atest
this is 333file
this is 444file
this is file
test1 = yes
test2 = yes
disable=no



注意行尾追加命令a后面的格式,前面两个斜杠,后面无斜杠
sed '/^disable/a\\this is a test'111.txt
sed '3a\\ this is a test' 111txt
下面是错误格式:
sed '3a\this is a test\' 111.txt


前面说了行尾追加,行内追加(即行内修改)如何做?实际是采用替换s/&

[macg@machome ~]$ sed 's/disable/& this istest/' 111.txt
实际是用& this istest替换disable
注意&即代表前面的disable
this is 111file
this is 222file
disable this is test = yes
this is 333file
this is 444file
this is file
test1 = yes
test2 = yes
disable this is test=no
this is 343file
this is 344file



行内追加的缺陷:如果用此法实现行尾追加,就必须把整个行不错一句的敲成pattern

[macg@machome ~]$ sed 's/disable = yes/& this istest/' 111.txt
this is 111file
this is 222file
disable = yes this istest

既然是追加到行尾,还是用a//yyy更合理,s/&只是在行内替换时有效


行内aaa后插入词bbb----------就是替换s/aaa/aaabbb/或s/aaa/&bbb


行内删除词------就是”空词//”替换------s/aaa//


r ------读文件 ,然后追加
另一种追加行,从一个文件中读出的行,追加到另一个文件pattern后

[macg@machome ~]$ more 22.txt
222222222222file
[macg@machome ~]$ more 111.txt
this is 111file
this is 222file
disable = yes
[macg@machome ~]$ sed '/disable/r 22.txt' 111.txt
this is 111file
this is 222file
disable = yes
222222222222file






=============================sed数字行操作===================================

代替/pattern/的另一种数字匹配句式-------匹配行号

  • 数字直接表示行号

所以不需要/pattern/
sed '1,10d' 删除文件中开头的10行
1,10 逗号是“从…到…”

  • 特殊符号表示行号

sed '$d' 删除文件中的最后一行
$表示最后一行


常见的两种数字标识行号用法

  • 显示文件中的第几行

[root@machome macg]#  sed -n '2p' 111.txt
this is222file

  • 显示多行

$ sed -n '2,7p'111.txt 逗号2,7相当于from … to
this is 222file
disable = yes
this is 333file
this is 444file
this is file
test1 = yes

sed '2,$d'111.txt 删除111.txt文件的第2行到末尾所有行


注意'2,7'与'2p;7p'的区别
'2,7p’表示2至7行
'2p;7p’显示2,7行


Command ‘=’ 显示行号
$ sed -n '/disable/=' 111.txt| sed -n '$p'
9 查找文件中含有disable的行的最后一行的行号


sed -n'$=' file  计算文件行数 (模拟 "wc-l")
$  -----------匹配文件最后一行
=  -----------显示当前行号
说是计算行号,实际是显示最后一行的行号

#  sed -n '$=' 111.txt
5


sed查找匹配中的最后一个并插入一行字符2011-10-25 12:51:13

分类: LINUX

#cat httpd.conf

LoadModule access_module modules/mod_access.so
LoadModule auth_module modules/mod_auth.so
LoadModule auth_anon_module modules/mod_auth_anon.so
LoadModule auth_dbm_module modules/mod_auth_dbm.so
LoadModule auth_digest_module modules/mod_auth_digest.so
LoadModule file_cache_module modules/mod_file_cache.so
LoadModule cache_module modules/mod_cache.so
LoadModule disk_cache_module modules/mod_disk_cache.so
LoadModule mem_cache_module modules/mod_mem_cache.so
LoadModule ldap_module modules/mod_ldap.so
LoadModule auth_ldap_module modules/mod_auth_ldap.so

只输出匹配LoadModule的第一行:
#sed -n '/LoadModule/{p;q}' httpd.conf

LoadModule access_module modules/mod_access.so

只输出匹配LoadModule的最后一行:
#sed -n '/^LoadModule/h;${x;p}' httpd.conf

LoadModule auth_ldap_module modules/mod_auth_ldap.so

我想在找到最后一个匹配的字符后插入一行字符

#cat test.sh

#!/bin/bash
n=`sed -n '/^LoadModule/h;${x;p}' httpd.conf|awk '{print $2}'`
sed "/${n}/ httpd.conf This is just a test" httpd.conf

[解析]
 这个要求稍微难一点,把匹配LoadModule的内容一直覆盖拷贝到缓冲空间中,注意是h,H是追加,不明白?再看看sed手册。这样sed一直读到最后一行,这时候遍历全文本只要是匹配LoadModule的内容就覆盖了缓冲空间,那肯定缓冲空间里是最后一个LoadModule行的内容,这时候x把模式空间和缓冲空间的内容交换,再打印输出即为最后一样匹配的内容了。


再附上awk的效果:

$ awk '!a[$1]++' httpd.conf
LoadModule access_module modules/mod_access.so

$ awk '/^LoadModule/{i=$0}END{print i}' httpd.conf
LoadModule auth_ldap_module modules/mod_auth_ldap.so


你可能感兴趣的:(shell,sed)