zoukankan      html  css  js  c++  java
  • sed学习笔记

    sed介绍

    sed是个流编辑器, 你可以想象成有一个管道, 文件从一端流进, 经过里面一系列加工后, 从另一端流出. 恩, 就这样理解算了. 这是一个很牛逼的工具, 作为Linux管理员, 最好熟悉下这个(还有awk, grep之类). 从一个简单例子开始:

    echo 'hello, tony' | sed 's/tony/jack/'
    

    输出: hello, tony. s替换的命令, /是分隔符. 就是把每中的tony换成jack. 当然, 你不一定要用/作为分隔符, 只要你愿意, 用什么都可以, 比如:

    echo 'hello, tony' | sed 's:tony:jack:'
    

    这里就用的:作的分隔符. 有一个要注意的是, sed默认替换行为是只影响到每一行中的第一个匹配项, 如果要影响所有的, 则要在后面加上g:

    echo 'hello, tony! my name is tony too~' | sed 's/tony/jack/g'
    

    输出: hello, jack! my name is jack too~

    &可以引用被匹配的内容

    有时候我们替换的内容是基于被匹配的内容上加工后形成的, 所以要替换的文本是不确定的. &可以引用前面匹配的内容:

    echo 'hello, tony! my name is tony too~' | sed 's/tony/&2/g'
    

    输出: hello, tony2! my name is tony2 too~. 注意上面把前面匹配的tony替换成了tony2.

    sed和扩展正则表达式

    我们知道在Linux系统中正则表达式有基本的和扩展的, 所谓扩展, 就是功能更丰富一些. 如下:

    echo '123 abc' | sed -r 's/[1-9]+/& &/'
    

    输出: 123 123 abc. 这里, 我们把一个数字组成的词复制一份. 在sed中, -r选项就是开启扩展正则功能, 因为+属于扩展正则的功能, 如果不开启的话, 会被解析成普通的字符.

    利用分组(1, 2, ... , 9)

    我们知道在正则表达式里, 可以用()进行分组, 这在sed里同样可以利用. 例子:

     echo 'hello, tony jack' | sed -r 's/([a-z]+) ([a-z]+)/2 1/'
    

    输出: hello, jack tony. 把tonyjack两个单词对换了. 1, 2, ... , 9 分别对应前面正则里的分组1, 分组2, ... , 分组9, 最多9个. 注意一点, 分组引用不只是只能出现在分隔符右边, 也可以出现在左边, 如:

    echo 'hello, tony tony yes ok ok' | sed -r 's/([a-z]+) 1/1/g'
    

    输出: hello, tony yes ok. 这里的功能是去重.
    在这前提到s命令后面加g, 会切换到全匹配模式, 即会扫描整行全部查找(默认只匹配第一个). 有时候我们的需求是确定匹配替换指定的第几个而不是全部, 可以在s的命令后面加上数字来指示. 例子:

    echo 'hello world haha!' | sed 's/[a-z][a-z]*/T/2'
    

    输出: hello T haha! 可以看到现在匹配替换的是第2个. 我们也可以结合g数字一起放到命令的后面组合使用, 表示从能匹配的第n个开始的后续所有匹配项. 举例:

    echo 'hello world haha!' | sed 's/[a-z][a-z]*/T/2g'
    

    输出: hello T T!. 可以看到, 现在是替换了从第2个开始的所有单词(由小写的a~z组成的单词).

    /p 打印匹配行

    sed默认行为是打印所有的行, 如果是s命令, 就用处理过的行替换处理前的行. 用g标识可以改变这一行为, 它会单独打印所匹配或者处理过的行. 例子:

    printf 'my name is
    haha, jack
    ' | sed 's/my/your/p'
    # 输出
    # your name is
    # your name is
    # haha, jack
    

    your name is这行输出了两次, 一次是sed命令自动输出, 另一次是标识p影响的作用. 如果我们现在只想打印匹配的行, 不要自动输出所有的行, 可以用-n选项, 例子:

    printf 'my name is
    haha, jack
    ' | sed -n 's/my/your/p'
    # 输出:
    # your name is
    

    可以看到, 现在只有能匹配的行才能输出了.

    I标识

    可以通过I标识来打开不区分大小写匹配. 例子:

    echo 'hello, tony' | sed 's/Tony/jack/I'
    # 输出:
    # hello, jack
    

    如果后面不加I标识, 则不会匹配成功.

    一行执行多个命令

    前面例子中每次只能执行一次s命令, 如果要处理多个命令怎么做呢, 当然我们可用管道把命令串起来, 就像:

    echo 'hello, tony and jack' | sed 's/tony/Tony/' | sed 's/jack/Jack/'
    # 输出:
    # hello, Tony and Jack
    

    但是在Linux中能一句话说清楚的就不绕个圏. 可以用-e选项来执行多个命令, 这样在sed处理每行时, 会依次执行. 例子:

    echo 'hello, tony and jack' | sed -e 's/tony/Tony/' -e 's/jack/Jack/' 
    # 输出:
    # hello, Tony and Jack
    

    选择要处理的行(addresses)

    有时候我们我们只希望处理一些特定的行而并不是文件的所有行, sed当然支持这样的功能, 它通restriction command这样的语法实现. 其中restriction就是限制要处理的行. 比如下面一些场景:

    • 指定要处理的行数, 比如第8行
    • 指定某个范围内的所有行, 比如第1行到第8行
    • 包括某个模式匹配的所有行
    • 从文件的第一行到指定匹配某个模式的行
    • 从指定匹配的行到文件的最后一行
    • 从一个模式匹配到别一个模式匹配行当中的所有行

    指定行数

    这是最简单的指定限制, 通过指定行数来处理, 例子:

    sed '1 s/hello/byby/' test.txt
    

    s替换命令只会在第一行生效

    正则模式匹配

    只有那些符合指定正则模式匹配的行才会处理, 例子:

    sed '/^[0-9][0-9]*/ s/hello/byby/' test.txt 
    

    只处理那些开头是数字的行.

    行数范围

    我们可以处理指定从第几行到第几行之间的所有行处理, 例子:

    # 处理第10行到第20行之间的数据
    sed '10,20 s/hello/byby/' test.txt
    # 处理第10到最后一行的所有数据
    sed '10,$ s/hello/byby/' test.txt 
    

    模式范围匹配

    从匹配的第一个模式开始, 一直到第二个模式匹配结束.

    sed '/start/,/end/ s/hello/byby/' test.txt 
    

    start开始处理, 到end结束.

    删除命令d

    前面讲的s是替换命令, d是删除命令. 例子:

    # 删除第2行到第三行之间的所有行
    sed '2,10 d' test.txt
    

    我们经常遇到一个场景是删除一个配置文件(properties)的所有注释, 可以这样写:

    sed -e 's/#.*//' -e 's/[ ^I]//' -e '/^$/ d'  test.txt
    

    上面这句由三个子命令组成, 它们的执行顺序也很重要. 分别来看一下. s/#.*//是把所有由#开头的内容去掉, 但是如果#前面有空格(space or tab), 就要做第二个命令处理: s/[ ^I]//, 就是把所有的空格去掉, 注意的是^I就是表示Tab. 最后一个命令就是所有空行(空行有两个来源, 一是文件本身的空行, 二是通过前面两条命令产生的空行)都通过命令d删除.

    反转命令: !

    !可以置反命令操作, 比如!d就是不删除的意思. 如下几个命令返回的结果是一样的, 都是只只输出第1到10行:

    sed -n '1,10 p'
    sed -n '11,$ !p'
    sed '1,10 !d'
    sed '11,$ d'
    

    退出命令

    遇到满足条件时退出流编辑操作, 如下:

    sed '11 q' test.txt
    

    只打印到第10行. 到第11行时就会退出. 因这退出操作的特殊性, 这个命令不支持范围匹配操作, 比如sed '2,3 q'就是错误的, 这个很好理解.

  • 相关阅读:
    vue中height设置为100%却无法铺满整个页面
    cpp快速上手
    CSP_2020061_线性分类器
    cpp快速上手
    算法笔记
    cpp中set的使用
    cpp中vector的使用
    常用命令
    常用git命令
    Linux使用docker安装fastfs
  • 原文地址:https://www.cnblogs.com/jcli/p/4088514.html
Copyright © 2011-2022 走看看