zoukankan      html  css  js  c++  java
  • sed 命令详解

    sed
    用于筛选和转换文本的流编辑器

    描述:
    sed是一个流编辑器,流编辑器对一个输入流执行基本的文本转换(输入流来自文件或者管道行)。虽然在某些方面类似于很多可运行脚本的编辑器,但是sed的工作方式是每次只处理一个输入(可以理解为一个模式空间),因此更高效。但是sed在管道中过滤文本的作用使它明显区别于其他类型编辑器。

    命令格式:
    sed [OPTION] {script} file

    选项
    -n, --quiet, --silent
        抑制模式空间的自动打印
        例如
    echo -e "abc
    def" | sed 'p'
    #输出 abc
    #    abc
    #    def
    #    def
    
    echo -e "abc
    def" | sed -n 'p'
    #输出 abc
    #    def
    -e script, --expression=script
        添加脚本到将要被执行的命令
        例如
    echo -e "abc
    def" | sed -n -e 's/abc/ghi/' -e 'p'
    # 输出 ghi
    #     def
    -f script-file, --file=script-file
        将脚本文件的内容添加到要执行的命令
    --follow-symlinks
        处理符号链接
    -i[SUFFIX], --in-place[=SUFFIX]
        编辑文件(如果提供了SUFFIX ,则对原文件先进行备份)
        例如
    sed -i_bak '1d' aaa
    # 将先生成aaa的备份文件aaa_bak
    -l N, --line-length=N
        为’l‘命令指定希望的行折叠长度
    --posix
        禁用所有的GNU扩展。
    -r, --regexp-extended
        在脚本中使用扩展的正则表达式。
    -s, --separate
        将文件视为单个独立的文件,而不是将它们视为整个连续的字符流。
    -u, --unbuffered
        从输入中加载尽可能少量的数据并且更频繁的刷新
    --help
        显示帮助并且退出
    --version
        输出版本信息并退出

    命令

    0地址命令
    : label
        为b和t命令定义标签。
    #comment
        注释一行
    }
        块结束符号

    0地址或者1地址命令
    =
        打印当前的行号
    a 
        text
        追加新行
        追加文本,(模式空间内的)每一行后都将追加(新行)反斜杠后的文本。
        例如
    echo "abc" | sed 'adef'
    # 输出 abc
    #     def
    i 
        text
        插入新行
        插入文本, (模式空间内的)每一行前都将插入(新行)反斜杠后的文本。
        例如
    echo "abc" | sed 'idef'
    # 输出 def
    #     abc
    q [exit-code]
        立即退出sed脚本不处理任何更多的输入, 除非自动打印是未禁用的情况下当前的模式空间将被打印。退出码参数是一个GNU扩展。
    Q [exit-code]
        立即退出sed脚本不处理任何更多的输入。退出码参数是一个GNU扩展。
    r filename
        追加从filename读取的文本
    R filename
        追加从filename读取的一行。每次调用命令从文件中读取一行。这是一个GNU扩展。

    接受地址范围的命令
    {      
        块命令的开始,
    b label
        跳转到标签,如果label省略,跳转到命令结尾。
    c 
       text
       行替换
       用text替换选中的行,每一行都将被反斜杠后的文本替换。
       例如
    echo -e "abc
    def" | sed 'cghi'
    # 输出 ghi
    #     ghi
    d
        删除模式空间。启动下一个循环。
    D
        如果模式空间内没有换行,开启一个新的循环如同d命令被发布。否则,删除模式空间的文本直到换行,并且在新产生的模式空间中重启循环,不从输入读入新行。
        这个怎么理解呢?当模式空间有多行时,D命令每次只删除一行,然后从下一行开始新的循环,这里的下一行是模式空间中的第二行,所以不从输入读入新行。
        而d命令就会把模式空间全部删除。然后从下一行开始循环,这里的下一行就是从输入读取的新行了。
        例如
    echo -e "abc
    def
    ghi
    jkl" | sed -n 'N;/abc
    def/d;p'
    # 输出 ghi
    #     jkl
    # sed共执行了2次循环,第一次循环如下
    #     N追加了一行,模式空间内容为"abc
    def";删除模式空间;开始下一个循环,读入输入的第一行,模式空间内容为"ghi";
    # 第二次循环如下
    #     N追加了一行,模式空间内容为"ghi
    jkl";删除操作未执行;打印模式空间。
       
    echo -e "abc
    def
    ghi
    jkl" | sed -n 'N;/abc
    def/D;p;p'
    # 输出 def
    #     ghi
    #     def
    #     ghi
    # sed共执行了2次循环,第一次循环如下
    #     N追加了一行,模式空间内容为"abc
    def";删除模式空间的第一行,模式空间内容为"def";开始下一个循环;
    # 第二次循环如下
    #     N追加了一行,模式空间内容为"def
    ghi";删除操作未执行;打印模式空间,打印模式空间。  
    h H
        复制/追加 模式空间到保持空间。
    g G
        复制/追加 保持空间到模式空间。
        例如
    echo -e "abc
    def" | sed -n 'h;n;g;p'
    # 输出 abc
        
    echo -e "abc
    def" | sed -n 'h;n;G;p'
    # 输出 def
    #     abc
    
    echo -e "abc
    def" | sed -n 'h;n;H;G;p'
    # 输出 def
    #     abc
    #     def
    l
        用视觉明确的格式列出当前行。
    l width
        用视觉明确的格式列出当前行,在第width个字符处阻断(换行)。这是一个GNU扩展。
        例如
    echo -e "abc
    def" | sed -n 'N;l'
    # 输出 abc
    def$
    echo -e "abc
    def" | sed -n 'N;l 4'
    # 输出 abc
    #     
    d
    #     ef$
    n N
        读取/追加 输入的下一行到模式空间。
        例如,下面的例子体现了大小写n命令的区别
    echo -e "abc
    def" | sed -n 'n;p'
    # 输出 def
        
    echo -e "abc
    def" | sed -n 'N;p'
    # 输出 abc
    #     def
    p
        打印当前的模式空间。
    P
        打印(的内容只)到当前模式空间的第一个换行符。只打印一行的意思。
        例如,下面的例子体现了大小写p命令的区别
    echo -e "abc
    def" | sed -n 'N;/abc
    def/p'
    # 输出 abc
    #     def
       
    echo -e "abc
    def" | sed -n 'N;/abc
    def/P'
    # 输出 abc
    s/regexp/replacement/
        用replacement替换匹配的内容
        尝试对模式空间匹配正则表达式。如果成功,用replacement替换掉匹配的部分。replacement可能包含特殊的字符&引用已匹配的那部分。特殊的转义1到9引用正则表达式中对应的子表达式。
        例如
    echo "abc" | sed 's/abc/def/'
    # 输出 def
    
    echo "abc" | sed 's/abc/&def/'
    # 输出 abcdef
        关于s命令的GNU扩展会在后文中描述,包括替换模式和其他选项
    t label
        切换到分支label。
        自从上一个输入行被读取并且(执行了)t或者T命令,如果s///已经完成一个成功的替换,切换到分支label;如果省略了标签,则切换到脚本的结尾。
    T label
        自从上一个输入行被读取并且(执行了)t或者T命令,如果s///连一个成功的替换都没有完成,切换到分支label;如果省略了标签,则切换到脚本的结尾。这是一个GNU扩展。
    w filename
        写当前的模式空间到文件filename。
    W filename
        写当前模式空间的第一行到文件filename。这是一个GNU扩展。
    x      
        交换模式空间和保持空间的内容。
    y/source/dest/
        将模式空间内source里的字符转换成dest里对应的字符。
        例如
    echo "axxbxxcxx" | sed 'y/abc/123/'
    # 输出 1xx2xx3xx

    sed命令可以不给出地址,在这种情况下将对所有的输入行执行命令;
    给出一个地址,这种情况下只对匹配的输入行执行命令;
    或者给出2个地址,这种情况下将对匹配的范围内(第一个地址开始持续到第二个地址)的所有行执行命令。
    关于地址范围的三个注意事项:
    1 语法是 addr1,addr2 (地址用逗号分割);
    2 已经匹配的addr1的行总是被接受的,即使地址2选择了一个较早的行(行号小于地址1);
    3 如果addr2是一个正则表达式,它不会针对已经匹配的地址1的行进行测试。
    如何理解第二条?就是说如果addr1匹配第5行,在第5行之后没有匹配addr2的行,则将匹配第5行到输入的结尾。
    那么 6,4 这种格式的地址呢? 6,4 = 6
    地址之后命令之前,一个 !(感叹号) 可能被插入,指明命令将被执行在不匹配的行上。
        例如
    echo -e "abc
    def" | sed -n '1!p'
    # 输出 def
    echo -e "abc
    def" | sed -n '$!p'
    # 输出 abc

    支持如下的地址类型:
    number     匹配指定的行(跨文件累计增加,除非命令行指定-s选项)。
    first~step 匹配first开始的每一个阶梯。
               比如 sed -n 1~2p 将打印输入流中的所有奇数行,地址 2~5 将匹配从第二行开始的每一个第五行,
               第一个数可以是0,这种情况下,sed操作每一个阶梯的倍数行。
    $          匹配最后一行
    /regexp/   匹配正则表达式regexp匹配的行。
    cregexpc  匹配正则表达式regexp匹配的行,c可以是任意的字符。
               比如有一行内容为abcdefg,则abcdefga将匹配该行。

    GNU sed 也支持一些特殊的2个地址的格式:
    0,addr2    开始于第一个地址匹配的状态,直到匹配addr2的行被找到.这类似于 1,addr2,除了addr2匹配输入的第一行,
               0,addr2 格式认为第一行是范围的末尾,而 1,addr2 格式认为第一行是范围的开始。
               这种格式只工作在addr2是正则表达式的情况。
               如果第一行匹配addr2,0,addr2 匹配的范围是第一行,而 1,addr2 匹配的范围是整个输入。
    addr1,+N   将匹配addr1和紧接着addr1的n行。
               6,+4 = 6,10
               6,+2 = 6,8
    addr1,~N   将匹配addr1和接下来的行,直到行号是n的倍数。
               6,~5 = 6,10
               6,~4 = 6,8

    s命令的GNU扩展
    在替换文本中可以包含一个特殊序列,由反斜杠引导一个字母组成。说明如下
    L  转换替换文本到小写格式直到 U 或者 E 出现
    l  转换下一个字符到小写格式
    U  转换替换文到大写格式直到 L 或者 E 出现
    u  转换下一个字符到大写格式
    E  停止由 L 或者 U 开启的大小写转换

    s命令后边可以跟如下标志
    g   应用替换到所有匹配正则表达式的内容,不仅仅是第一个。
    number  只替换第n个匹配。
    p  执行完替换,打印新的模式空间。
    w file-name
        执行完替换,写结果到命名的文件。
    e  该命令允许从shell命令管道输入模式空间。
    I
    i  
        正则表达式匹配时忽略大小写。
    M
    m
        大意是说^在匹配行首时,是从第0个位置开始还是从第一个字符开始?在有缩进的情况下。但是好像并没有测验出什么?
  • 相关阅读:
    JDK源码之LinkedList
    MySQL常规知识点总结
    根据不同分辨率载入相应CSS样式表
    关于1.0.0版Backbone.js调用validate
    弹性盒模型计算
    使用CocoaPods
    Objective-C中的Block[转]
    将UTF8编码转化为中文 - NSString方法
    添加第三方类库造成的Undefined symbols for architecture i386:编译错误
    App适配iPhone 6/ Plus和iOS 8:10条小秘诀
  • 原文地址:https://www.cnblogs.com/the-capricornus/p/5279979.html
Copyright © 2011-2022 走看看