Chinaunix首页 | 论坛 | 博客
  • 博客访问: 289302
  • 博文数量: 102
  • 博客积分: 230
  • 博客等级: 入伍新兵
  • 技术积分: 477
  • 用 户 组: 普通用户
  • 注册时间: 2010-12-13 15:58
文章存档

2014年(23)

2013年(2)

2012年(45)

2011年(32)

分类:

2012-04-11 18:08:28

原文地址:shell编程之sed 作者:shibaolan

2012年新增实际脚本
######################
替换文件 “$DOMAIN_HOME/etc/jetty-ssl.xml”
但bash里
  \$DOMAIN_HOME\/etc\/jetty-ssl\.xml
sed -i  's/\$DOMAIN_HOME\/etc\/jetty-ssl\.xml/ /g'
 find /kingdee/jetty/domains/ -name jetty.sh |xargs cat |grep \$DOMAIN_HOME\/etc\/jetty-ssl\.xml
 find /kingdee/jetty/domains/ -name jetty.sh |xargs  sed -i  's/\$DOMAIN_HOME\/etc\/jetty-ssl\.xml/ /g'
 find /kingdee/jetty/domains/ -name jetty-ssl.xml
 find /kingdee/jetty/domains/ -name jetty-ssl.xml -exec rm {} \;

很实用的一个查找文件并用同名文件替换
find /kingdee/jetty/domains/  -name  jetty-ssl.xml  -exec cp {} \;

定位到一行后对本行内容操作
sed '/two/ s/1/2/' samplefile

假定希望用 "2" 来替换 "1",但仅在单词 "two" 之后才作替换,而不是每一行的所有位置。通过指定在给出替换命令之前必须存在一次匹配,可以实现这一点

$ sed '/two/ s/1/2/' sample_one

定位到一行后对下一行内容操作
sed -i '/mongoFile/{n;s/28017/27017/;}' data.xml
对data.xml文件文件进行如下操作,先匹配mongoFile字符行,然后把下一行的"28017"替换成“27017”

在"lowResourcesMaxIdleTime" 增加一行“            true ”内容
 sed  '/lowResourcesMaxIdleTime/a \            true' -i jetty.xml  

find 与awk结合,打印文件名,注意必须在END里才能打文件名,在BEGIN里无法打印文件名,不知道为什么。
find /usr/local/nginx/conf/conf.d  -name "*.conf" -exec awk ' /10091/ {print $0} END {print FILENAME,"\n-------" }' {} \;
######################




一、sed (Stream Editor)

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 '/\ 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


awk 显示最后列的内容

explame=test.name.last.jar

echo $explame|awk -F  "." {'print $NF'}



20120725更新:


sed行处理详解(交换行,合并行,删除行等)

1.合并行

cat test1

1

2

3

4

合并上下两行

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

1    2

3    4

合并匹配模式及其下一行

sed '/2/{N;s/\n/\t/}' test1

1

2    3

4

合并所有行

sed ':a;N;s/\n/|/;ba;' test1

1    2    3    4

这个要注标一下:

我看了半天帮助才懂的

: label  建立 script file 内指令互相参考的位置 b label  将执行的指令跳至由 : 建立的参考位置

也就是循环了 首先建立一个参考位,然后开替换,找到换行符“\n”用“|”来代替换,然后遇到跳转到参考位置,再次执行,直到最后一行


2.交换行

2.1已知行号时交换两行

cat test

baidu music so terrible so bad

microsoft haha haha

yahoo byebye

google princess so good 

这里是交换1,4行.当然你可以根据自己需要修改

for(( i=1;i<=4;i++ )); do case $i in 1) sed -n 4p test;; 4) sed -n 1p test;; *) sed -n ${i}p test;; esac; done

google princess so good 

microsoft haha haha

yahoo byebye

baidu music so terrible so bad

连续时好说:

sed '1{h;d};2{G}' test

microsoft haha haha

baidu music so terrible so bad

yahoo byebye

google princess so good

2.2不知道行号

要交换的两行是连续行的情况下:

sed '/baidu/{h;d};/microsoft/{G}' test

microsoft haha haha

baidu music so terrible so bad

yahoo byebye

google princess so good

ps:交换包含bai与microsoft的行

两行不连续的情况:

sed '/baidu/{:a;N;/google/!ba;s/\([^\n]*\)\n\(.*\)\n\(.*\)/\3\n\2\n\1/}' test

google princess so good 

microsoft haha haha

yahoo byebye

baidu music so terrible so bad

ps:交换含有baidu与google的行

研究了下写了个不论连续不连续的都可以的:

sed '/baidu/{:a;N;/microsoft/!ba;/[^\n]*baidu[^\n]*\n[^\n]*microsoft[^\n]*$/{s/\([^\n]*baidu[^\n]*\)\n\(.*\)/\2\n\1/};s/\([^\n]*\)\n\(.*\)\n\(.*\)/\3\n\2\n\1/}' test

microsoft haha haha

baidu music so terrible so bad

yahoo byebye

google princess so good

sed '/baidu/{:a;N;/google/!ba;/[^\n]*baidu[^\n]*\n[^\n]*google[^\n]*$/{s/\([^\n]*baidu[^\n]*\)\n\(.*\)/\2\n\1/;};s/\([^\n]*\)\n\(.*\)\n\(.*\)/\3\n\2\n\1/}' test

google princess so good 

microsoft haha haha

yahoo byebye

baidu music so terrible so bad

ps:上面代码

/baidu/{....} 遇到含有baidu的行,开始做{}中的命令序列

:a;N;/google/!ba 循环读信息,直到读取google.

/[^\n]*baidu[^\n]*\n[^\n]*google[^\n]*$/这个就是说如果哦baidu与google之间只有一个\n,即这两个是连续行就:{s/\([^\n]*baidu[^\n]*\)\n\(.*\)/\2\n\1/;}交换这两行

如果不匹配上面的模式就是说不是连续行了.

s/\([^\n]*\)\n\(.*\)\n\(.*\)/\3\n\2\n\1/}

而在匹配连续行的情况下是不可能匹配上面表达式的.ok~~~~

3.交互奇偶行

sed '$!N;s/\([^\n]*\)\n\([^\n]*\)/\2\n\1/' test

microsoft haha haha

baidu music so terrible so bad

google princess so good 

yahoo byebye

5.删除空行

sed '/^$/d' test2

删除多个空行为一个空行

sed '/^$/{N;/^\n*$/D}' test2



下一个: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。


    sed 多行模式处理语句

    删除匹配的上一行:

    sed  'N;/\n.*urstring/!P;D' urfile

    1、方法

    输出奇数行 :

    sed -n 'p;n' file

    输出偶数行 :

    sed -n 'n;p' file

    2、原理

    p 打印模式空间中的内容

    n 延续到下一输入行;允许跨行的模式匹配语句多行模式,将下一行内容读入模式空间覆盖以前内容)

    "p;n" 先打印一行,然后在读取下一行不作处理sed语句执行完成进入下一个循环,打印第三行,读取第四行不处理sed进入下一个循环......


    "n;p" 现读取下一行内容覆盖上一行,然后打印,sed语句执行完成进入下一个循环,读取第四行内容覆盖第三行内容,让后打印,sed进入下一个循环

    3、补充

    a) n与N区别

    n:读下一行到模式空间(覆盖原内容)

    N:追加下一行内容到模式空间(不覆盖原内容)

    b) p与P区别

    p:打印多行模式空间的所有行

    P:打印多行模式空间的第一部分

阅读(906) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~