Linux面试题之Sed命令44道应用练习题实战

Sed用法及习题精选

Sed工作原理

  • 原理

    1. 读入新的一行内容到模式空间(pattern space);
    2. 从指定的操作指令中取出第一条指令,判断是否匹配pattern;
    3. 如果不匹配,则忽略后续的编辑命令,回到第2步继续取出下一条指令;
    4. 如果匹配,则针对缓存的行执行后续的编辑命令(补充:执行完后,才进行默认输出[可以被-n选项抑制掉],然后再清空模式空间);完成后,回到第2步继续取出下一条指令;
    5. 当所有指令都应用之后,输出缓存行的内容;回到第1步继续读入下一行内容;
    6. 当所有行都处理完之后,结束;
  • 命令格式

    syntax:sed [option]… {Script} [FILE]…**

  • 常用格式

    sed 选项 地址编辑命令 文件

  • [option]

    -n : 不输出模式空间中的内容至屏幕,即关闭不能被模式匹配到的行到标准输出

    -e : 多想编辑命令一次执行

    -f FILE : 将编辑指令写入文件,调用FILE

    -r : 支持扩展正则表达式元字符

    -i : 直接修改原文件

    -i.bak : 修改源文件,但是会生成备份文件为.bak的文件

  • 地址

    1. 空地址:即对全文进行处理

    2. 单地址(line-address)

    3. 步进地址表示法

      1~2 : 所有奇数行: sed -n ‘1~2p’ test
      2~2 : 所有偶数行: sed -n ‘2~2p’ test

    4. 地址对(address)

      N,M : 第N到M行

      N,+M : 从N行向下M行

      N,/pattern/ : 从N到正则匹配到的行

      /pattern1/,/pattern2/ : 从模式1到模式2匹配到的行

      $ : 表示最后一行

  • 模式空间(基础命令)

    1. d : 删除模式空间内容

    2. [line-address]a\STRING : append,在指定行下一行追加内容

    3. [line-address]i\STRING : insert,在指定行上一行追加内容

    4. c\STRING : change,改变指定行内容

    5. p : print,打印模式空间的内容

    6. l : list,输出行控制符

    7. = : 输出行号

    8. s/RegExp/REPLACE/g : search,搜索与替换,"/"可以换成其他符号:#@%…

    • 在s///中使用分组及后向引用
    • eg: sed -r ‘s/i love (\S+) and (\S+)/\1 love \2/’ /tmp/test
    1. n : next,读取下一行

    2. y/abc/xyz/ : 转换字符,a转成x,b转成y,c转成y,一一对应转换

    3. w FILE : write,保存内容

      • [line-address]r FILE : read,将文件内容读取到指定行
    4. [line-address]q : quit,读取到匹配行之后退出

  • 模式空间(高级命令)

    1. N : 将下一行读到模式空间,用\n连接上一行 (注意:是模式空间同一行)
    2. P : 输出上一行内容
    3. D : 删除上一行内容,并且继续执行指令 保持空间命令
    4. h/H : hold,将模式空间内容复制(h),通过\n追加(H)到保持空间
    5. g/G : get,将保持空间内容复制(g),通过\n追加(G)到模式空间
    6. x : exchange,将保持空间内容和模式空间内容交

习题1

  1. 所有以192.168.0.1开头的行都会被替换成它自己加localhost

    [root@ ~ 10:42:37]#echo -e '192.168.0.1 xixi\naaa\n192.168.0.1\nbbb'|   \
     sed -r 's/192.168.0.1/&localhost/g'   #-r 支持正则表达式
    192.168.0.1localhost xixi
    aaa
    192.168.0.1localhost
    bbb
    
  2. 替换 digit 数字 ,内容为 相同数字

    [root@ ~ 10:42:37]#cat test
    aa digit3
    digit44bb
    12digitb 
    [root@ ~ 10:42:37]# sed -r 's/digit([0-9])/\1/g' test
    aa 3						#利用后向引用和s///进行替换
    44bb
    12digitb
    
  3. love被标记为\1,所有loverable会被替换成lovers,并打印出来

    [root@ ~ 10:42:37]#cat test
    loverabl1
    lover
    loverable
    [root@ ~ 10:58:46]#sed -r 's/(love)rable/\1rs/g' test
    loverabl1						#同样使用后向引用
    lover
    lovers
    
  4. 使用n或p打印奇数行或偶数行(列出4种方法)

    #奇数行
    echo -e "a\nb\nc\nd\ne"|sed -n 'P;N'
    echo -e "a\nb\nc\nd\ne"|sed -n 'p;n'
    echo -e "a\nb\nc\nd\ne"|sed -n '1~2p'
    #偶数行
    echo -e "a\nb\nc\nd\ne"|sed -n 'n;p'
    echo -e "a\nb\nc\nd\ne"|sed -n '2~2p'
    

习题2

  1. 对于包含test到west之间的行,每行加上字符串’aaa bbb’

    [root@ ~/test 04:12:45]#cat test
    a test hehe west xixi 
    test haha wes .
    [root@ ~ 11:15:37]#sed -r 's/(test.*west.*$)/\1aaa bbb/g' test
    a test hehe west xixi aaa bbb			#使用后向引用 \1 指代前面括号里的内容
    test haha wes .
    
  2. 查找包含line1的行到包含line2的行之间的所有aa bbb替换成AA BBB

[root@ ~ 10:42:37]#cat test 
aa bbb line1 aa 
 aa bbb 
 cc aa bbb 
 line2  
 aa bbb 
 line1
[root@ ~ 11:20:23]#sed '/line1/,/line2/s/aa bbb/AA BBB/g' test
AA BBB line1 aa 
 AA BBB 
 cc AA BBB 
 line2  
 aa bbb 
 line1 
  1. 匹配关键字并显示后几行
  • 显示第一次匹配到的3到最后一行输出

    [root@ ~ 10:42:37]#cat test 
    1
    2
    3
    4
    5
    6
    [root@ ~ 11:34:17]#echo -e '1\n2\n3\n4\n5\n6' |sed -n '/3/,$p'
    3
    4
    5
    6
    
  • 显示第一次匹配到的3到向下两行输出

    [root@ ~ 10:42:37]#cat test
    1
    2
    3
    4
    5
    6
    [root@ ~ 11:48:19]#sed -n  -r '/3/{N;N;p;q}'  test
    3			#利用两次N将后两行追加到模式空间(同一行,\n分隔离),并打印,默认抑制
    4			#注意:第二次匹配到的就不行,所以第一次匹配操作完就退出
    5
    
  1. 逆序显示文本内容

    [root@ ~ 12:09:52]#echo -e '1\n2\n3\n4\n5\n6' |sed -n '1!G;h;$p'
        
    6		#处理行不是第一行,就从保持空间的内容追加到模式空间(形成最新的逆序串)
    5		#然后这个串再覆盖保持空间里
    4		#当处理完最后一行后,打印保持空间的内容
    3
    2
    1
    [root@ ~/test 04:22:22]#sed -n '1h;1!{G;h};$p' test #也可以
    
  2. 取出文本中最后一行

    [root@ ~ 12:11:17]#echo -e '1\n2\n3\n4\n5\n6' |sed -n '$p'
    6								#最后一行,打印
    
  3. 删除原有的所有空白行,而后为所有的非空白行后添加一个空白行

    [root@ ~ 09:41:39]#echo -e 'a\n\nb\n\nc\nd'
    a
    
    b
    
    c
    d
    [root@ ~ 09:41:32]#echo -e 'a\n\nb\n\nc\nd'|sed -n -r '/.+/{G;p}'
    a
    
    b
    
    c
    
    d
    
    
  4. 在原有的每行后方添加一个空白行

    [root@ ~ 09:42:27]#echo -e 'a\nb\nc\nd'
    a
    b
    c
    d
    [root@ ~ 09:42:06]#echo -e 'a\nb\nc\nd'|sed -n 'G;p'
    a
    
    b
    
    c
    
    d
    
    
  5. 显示最后一行的行号,一般可用于显示文本的总行数

    [root@ ~ 09:50:43]#echo -e 'a\n\n\nb\n\n\nc\nd'
    a
    
    
    b
    
    
    c
    d
    [root@ ~ 10:00:23]#echo -e 'a\n\n\nb\n\n\nc\nd'|sed -n '$=' #打印尾行行号
    8
    
  6. 显示所有行的行号,但空行不显示行号

    [root@ ~ 09:50:43]#echo -e 'a\n\n\nb\n\n\nc\nd'
    a
    
    
    b
    
    
    c
    d
    [root@ ~ 10:02:19]#echo -e 'a\n\n\nb\n\n\nc\nd'|sed -n '/^$/!='
    1													#不是空行就打印行号
    4
    7
    8
    

习题3

  1. 删除所有的空行,并在每行后面增加一个空行

    [root@ ~/test 04:09:19]#echo -e "\na\n\n\nb\n\nc"
    
    a
    
    
    b
    
    c
    [root@ ~/test 04:12:40]#echo -e "\na\n\n\nb\n\nc"|sed -r -n '/^$/!{s/(.*)/\1\n/;p}'  #对不是空行的情况尾部增加一个换行符,并且打印,别忘了抑制默认输出
    a
    
    b
    
    c
    
    
  2. 在查找到的行前增加一个空行

    [root@ ~/test 04:02:36]#echo -e "a\nb\nc\nd\nd\ne\nf"
    a
    b
    c
    d
    d
    e
    f
    [root@ ~/test 04:01:56]#echo -e "a\nb\nc\nd\nd\ne\nf"|				\     sed -r 's/(^c.*)/\n\1/'
    a
    b
    
    c
    d
    d
    e
    f
    
  3. 统计文本的行数

    [root@ ~/test 03:58:32]#echo -e "a\nb\nc\nd\nd\ne\nf"|sed -n '$='
    7
    
  4. 将没一行的行首的空白字符(空格,制表符)删除

    [root@ ~/test 03:55:27]#echo -e "   a\n\ta\ta\n a\na\ta"
       a
    	a	a
     a
    a	a
    [root@ ~/test 03:55:53]#echo -e "   a\n\ta\ta\n a\na\ta"|			\	     sed -r 's/^( +|\t+)//'
    a
    a	a
    a
    a	a
    
  5. 将文本中的’aaa’,‘bbb’,‘ccc’都替换为’ttt’

    [root@ ~/test 03:49:50]#echo -e "aaa bbb\nbbb\nccc aaa"
    aaa bbb
    bbb
    ccc aaa
    [root@ ~/test 03:52:06]#echo -e "aaa bbb\nbbb\nccc aaa"|			\        	sed -r 's/aaa|bbb|ccc/ttt/g'    #全局替换,若缺少g则每行最多替换第一个满足的字串 
    ttt ttt
    ttt
    ttt ttt
    
  6. 将’yes’替换成’no’,并且只在行中未出现字串’hello’的情况下替换

    [root@ ~/test 03:49:09]#echo -e "hello yes sir\nhi yes sir"
    hello yes sir
    hi yes sir
    [root@ ~/test 03:49:39]#echo -e "hello yes sir\nhi yes sir"|			\    sed  -r '/hello/!s/yes/no/'
    hello yes sir
    hi no sir
    
  7. 将每行的字符逆序显示

    [root@ ~/test 04:12:45]#cat test
    BEACH HAHA AMAZON
    ALIBABA HAHA TENCENT
    PINGLINGLAB HAHA GDUT
    [root@ ~/test 04:22:22]#sed -n '1h;1!{G;h};$p' test
    NOZAMA AHAH HCAEB
    TNECNET AHAH ABABILA
    TUDG AHAH BALGNILGNIP
    
  8. 将数字’1234567’显示为1,234,567

    [root@ ~/test 03:46:11]#echo '1234567'|sed  's/1/1,/;s/4/4,/'
    1,234,567
    
  9. 模拟 tail -1 命令的效果

    [root@ ~/test 03:33:01]#cat error.log
    APPLE XIXI GOOGLE
    BEACH HAHA AMAZON
    FACEBOOK XIXI NETEASE
    ALIBABA HAHA TENCENT
    ORICLE XIXI SUN
    PINGLINGLAB HAHA GDUT
    [root@ ~/test 03:36:40]#sed -n '$!d;$p' error.log  #不是尾行就删除,是就打印
    PINGLINGLAB HAHA GDUT
    
  10. 将如下内容通过sed处理

aaa
bbb
ccc
ddd
eee
fff

变为

 aaa bbb
 ccc ddd
 eee fff
[root@ ~/test 02:59:42]#echo -e 'aaa\nbbb\nccc\nddd\neee\nfff'|sed -n 'N;s/\n/ /;p'
aaa bbb
ccc ddd
eee fff

习题4

  1. 将error.log中匹配到的内容保存至某文件

    [root@ ~/test 03:33:01]#cat error.log
    APPLE XIXI GOOGLE
    BEACH HAHA AMAZON
    FACEBOOK XIXI NETEASE
    ALIBABA HAHA TENCENT
    ORICLE XIXI SUN
    PINGLINGLAB HAHA GDUT
    [root@ ~/test 03:33:06]#sed '/HAHA/w ./test' error.log   										#含有HAHA一行就保存到test文件里
    [root@ ~/test 03:33:48]#cat ./test
    BEACH HAHA AMAZON
    ALIBABA HAHA TENCENT
    PINGLINGLAB HAHA GDUT
    
  2. 将文件中的内容读入到匹配的内容后面

    [root@ ~/test 03:03:04]#cat test
    APPLE XIXI GOOGLE
    BEACH HAHA AMAZON
    FACEBOOK XIXI NETEASE
    ALIBABA HAHA TENCENT
    ORICLE XIXI SUN
    PINGLINGLAB HAHA GDUT
    [root@ ~/test 03:25:39]#cat test|sed -r -n '/HAHA/p;/HAHA/!H;$g;s/^\n//;$p' #以HAHA开头打印,不以HAHA开头追加到扩展空间
    BEACH HAHA AMAZON				 #处理到最后一行,将扩展空间内容覆盖到模式空间
    ALIBABA HAHA TENCENT			 #将模式空间开头的换行符置空
    PINGLINGLAB HAHA GDUT			 #将模式空间打印,打印内容是不以HAHA开头的行
    APPLE XIXI GOOGLE
    FACEBOOK XIXI NETEASE
    ORICLE XIXI SUN
    
    
  3. 打印匹配到的内容,并显示行号

    [root@ ~/test 01:31:53]#cat sedtest |sed -r -n '/ddd$/{=;p}'
    7			#行号
    7ddd		#行号对应内容
    14
    14aaaddd
    21
    21aaa ddd
    
  4. 删除匹配到的行的下一行

    [root@ ~/test 01:20:14]#echo -e '1\n2\n3\n4\n5\n6\n7\n8'|sed -n '/^4/{h;n;g};p'
    1
    2
    3
    4
    6
    7
    8
    
  5. 删除匹配到的行和下一行

    [root@ ~/test 01:23:06]#echo -e '1\n2\n3\n4\n5\n6\n7\n8'|sed  '/^4/{N;d}'
    1
    2
    3
    6
    7
    8
    
  6. 删除文件每行中的第一个字

    [root@ ~/test 01:25:39]#cat sedtest |sed -r 's/^.//g'
    
  7. 删除文件每行的第二个字符

    [root@ ~/test 01:27:10]#cat sedtest |sed -r 's/(.)(.)(.*)/\1\3/g'
    
  8. 删除文件每行的最后一个字符

    [root@ ~/test 01:28:11]#cat sedtest |sed -r 's/(.*)./\1/g'
    
  9. 删除文件每行的倒数第二个字符

    [root@ ~/test 01:28:11]#cat sedtest |sed -r 's/(.*).(.)/\1\2/g'
    
  10. 删除每行的最后一个单词

    [root@ ~/test 02:47:38]#cat test
    i have a dream.
    this is a homework .
    why don't you join Pinginglab?
    [root@ ~/test 02:54:30]#cat test|sed -r 's/(.*) ([a-zA-Z]+)(.)/\1\3/g'
    i have a.
    this is a .
    why don't you join?
    

习题5

  1. 删除一个文件中的所有的数字

    [root@ ~/test 10:35:00]#cat sedtest 
    aaa 11bb22
    bb2 33cc44
    aaaaaaaaaa
    [root@ ~/test 10:35:56]#sed -r 's/[0-9]//g' sedtest
    aaa bb
    bb cc
    aaaaaaaaaa
    
  2. 将时间格式 yy/mm/dd 的日期换成 yy:mm:dd 的格式( data 命令实现:如2016/08/15变成 2016:08:16)

    [root@ ~/test 10:38:46]#cat sedtest
    a2016/05/31a
    a 11/01/01a
    3/04/30 a
    [root@ ~/test 10:46:17]#sed  -r 's/\b([0-9]+)\/([0-9]{2})\/([0-9]{2})\b/\1:\2:\3/g' sedtest 
    a2016/05/31a
    a 11/01/01a
    3:04:30 a
    
  3. 显示奇数行

    [root@ ~/test 10:46:37]#cat sedtest 
    a2016/05/31a
    a 11/01/01a
    3/04/30 a
    [root@ ~/test 11:05:36]#cat sedtest | sed  -n '1~2p'
    a2016/05/31a
    3/04/30 a
    
  4. 删除模式一到模式二匹配到的行

    [root@ ~/test 11:07:52]#echo -e '1\n2\n3\n4\n5\n6' 
    1
    2
    3
    4
    5
    6
    [root@ ~/test 11:07:45]#echo -e '1\n2\n3\n4\n5\n6' |sed -r '/^2/,/^4/{d}'
    1
    5
    6
    
  5. 从指定行开始,每隔2行显示一次

    [root@ ~/test 11:07:52]#echo -e '1\n2\n3\n4\n5\n6' 
    1
    2
    3
    4
    5
    6
    [root@ ~/test 11:22:13]#echo -e '1\n2\n3\n4\n5\n6' |sed -n '2~3p'
    2
    5
    
  6. 删除文中的最后两行

    [root@ ~/test 11:38:53]#echo -e '1\n2\n3\n4\n5\n6'
    1
    2
    3
    4
    5
    6
    [root@ ~/test 05:14:34]#echo -e "1\n2\n3\n4\n5" |		\				sed  -r -n 'H;$g;$s/\n(.*)\n(.*)\n(.*)/\1/;$p'
    1
    2
    3
    
  7. 删除文中的空行

    [root@ ~/test 11:44:17]#echo -e '1\n\n2\n\n3\n4\n\n5\n6'
    1
    
    2
    
    3
    4
    
    5
    6
    [root@ ~/test 11:44:22]#echo -e '1\n\n2\n\n3\n4\n\n5\n6'|sed '/^$/d'
    1
    2
    3
    4
    5
    6
    
  8. 每隔5行增加一个空行

    [root@ ~/test 11:58:39]#echo -e '1\n2\n3\n4\n5\n6\n7\n8'
    1
    2
    3
    4
    5
    6
    7
    8
    [root@ ~/test 12:01:17]#echo -e '1\n2\n3\n4\n5\n6\n7\n8'|sed -r -n '0~5G;p'		#从开始起每逢五行从扩展空间追加一个换行符到模式空间,并打印模式空间内容
    1
    2
    3
    4
    5
    
    6
    7
    8
    
  9. 不显示指定字符开始的行

    [root@ ~/test 12:48:09]#echo -e '1\n2\n3\n4\n5\n6\n7\n8'|sed -r -n '/^4/d;p'			#不显示以4开头的行
    1
    2
    3
    5
    6
    7
    8
    
  10. 查找文件中1到20行之间,同事将’aaa’替换为’AAA’,‘ddd’替换成’DDD’

    [root@ ~/test 12:52:54]#sed -r '1,20y/aaa/AAA/;1,20y/ddd/DDD/' sedtest 
    1
    2
    3
    4
    5DDD AAA
    6
    7DDD
    8
    9
    10AAA
    11
    12
    13
    14AAADDD
    15
    16
    17
    18
    19
    20
    21aaa ddd   #可以看到哦第21行没有被替换
    

猜你喜欢

转载自blog.csdn.net/weixin_31789689/article/details/107943466