Sed - 正则表达式

  • 简述

    正是正则表达式使 SED 强大而高效。许多复杂的任务可以用正则表达式来解决。任何命令行专家都知道正则表达式的威力。
    与许多其他 GNU/Linux 实用程序一样,SED 也支持正则表达式,通常称为regex. 本章详细介绍正则表达式。本章分为三个部分:标准正则表达式、正则表达式的 POSIX 类和元字符。
  • 标准正则表达式

    行首 (^)

    在正则表达式术语中,插入 (^) 符号与行首匹配。下面的示例打印所有以模式“The”开头的行。
    
    [jerry]$ sed -n '/^The/ p' books.txt
    
    执行上面的代码,你会得到以下结果:
    
    The Two Towers, J. R. R. Tolkien 
    The Alchemist, Paulo Coelho 
    The Fellowship of the Ring, J. R. R. Tolkien 
    The Pilgrimage, Paulo Coelho
    

    行尾 ($)

    行尾由美元 ($) 符号表示。下面的示例打印以“Coelho”结尾的行。
    
    [jerry]$ sed -n '/Coelho$/ p' books.txt 
    
    执行上面的代码,你会得到以下结果:
    
    The Alchemist, Paulo Coelho 
    The Pilgrimage, Paulo Coelho
    

    单个字符 (.)

    Dot(.) 匹配除行尾字符之外的任何单个字符。下面的示例打印所有以字符“t”结尾的三个字母单词。
    
    [jerry]$ echo -e "cat\nbat\nrat\nmat\nbatting\nrats\nmats" | sed -n '/^..t$/p' 
    
    执行上面的代码,你会得到以下结果:
    
    cat 
    bat 
    rat 
    mat
    

    匹配字符集 ([])

    在正则表达式术语中,字符集由方括号 ([]) 表示。它用于仅匹配几个字符中的一个。以下示例匹配模式“Call”和“Tall”,但不匹配“Ball”。
    
    [jerry]$ echo -e "Call\nTall\nBall" | sed -n '/[CT]all/ p'
    
    执行上面的代码,你会得到以下结果:
    
    Call 
    Tall
    

    独家套装 ([^])

    在独占集中,插入符号否定方括号中的字符集。以下示例仅打印“Ball”。
    
    [jerry]$ echo -e "Call\nTall\nBall" | sed -n '/[^CT]all/ p'
    
    执行上面的代码,你会得到以下结果:
    
    Ball 
    

    字符范围 ([-])

    提供字符范围时,正则表达式匹配方括号中指定范围内的任何字符。以下示例匹配“Call”和“Tall”,但不匹配“Ball”。
    
    [jerry]$ echo -e "Call\nTall\nBall" | sed -n '/[C-Z]all/ p' 
    
    执行上面的代码,你会得到以下结果:
    
    Call 
    Tall
    
    现在让我们将范围修改为“AP”并观察结果。
    
    [jerry]$ echo -e "Call\nTall\nBall" | sed -n '/[A-P]all/ p' 
    
    执行上面的代码,你会得到以下结果:
    
    Call 
    Ball
    

    一次出现为零 (\?)

    在 SED 中,问号 (\?) 匹配零次或一次出现的前一个字符。以下示例匹配“行为”和“行为”。在这里,我们使用“\?”将“u”作为可选字符。
    
    [jerry]$ echo -e "Behaviour\nBehavior" | sed -n '/Behaviou\?r/ p' 
    
    执行上面的代码,你会得到以下结果:
    
    Behaviour 
    Behavior
    

    一次或多次出现 (\+)

    在 SED 中,加号 (\+) 匹配前一个字符的一次或多次出现。以下示例匹配一个或多个“2”。
    
    [jerry]$ echo -e "111\n22\n123\n234\n456\n222"  | sed -n '/2\+/ p'
    
    执行上面的代码,你会得到以下结果:
    
    22 
    123 
    234 
    222 
    

    零次或多次出现 (*)

    星号 (*) 匹配前面字符的零次或多次出现。以下示例匹配“ca”、“cat”、“catt”等。
    
    [jerry]$ echo -e "ca\ncat" | sed -n '/cat*/ p' 
    
    执行上面的代码,你会得到以下结果:
    
    ca 
    cat 
    

    恰好 N 次出现 {n}

    {n} 与前一个字符的“n”次完全匹配。以下示例仅打印三位数字。但在此之前,您需要创建以下仅包含数字的文件。
    
    [jerry]$ cat numbers.txt 
    
    执行上面的代码,你会得到以下结果:
    
    1 
    10 
    100 
    1000 
    10000 
    100000 
    1000000 
    10000000 
    100000000 
    1000000000
    
    让我们编写 SED 表达式。
    
    [jerry]$ sed -n '/^[0-9]\{3\}$/ p' numbers.txt 
    
    执行上面的代码,你会得到以下结果:
    
    100
    
    请注意,这对花括号被“\”字符转义。

    至少出现 n 次 {n,}

    {n,} 匹配至少“n”次出现的前一个字符。下面的示例打印所有大于或等于五位数的数字。
    
    [jerry]$ sed -n '/^[0-9]\{5,\}$/ p' numbers.txt
    
    执行上面的代码,你会得到以下结果:
    
    10000 
    100000 
    1000000
    10000000 
    100000000 
    1000000000 
    

    M 到 N 次出现 {m, n}

    {m, n} 匹配前一个字符的至少“m”个和最多“n”个出现。以下示例打印所有至少有五位但不超过八位的数字。
    
    [jerry]$ sed -n '/^[0-9]\{5,8\}$/ p' numbers.txt
    
    执行上面的代码,你会得到以下结果:
    
    10000 
    100000 
    1000000 
    10000000 
    

    管道 (|)

    在 SED 中,管道字符的行为类似于逻辑 OR 操作。它匹配管道两侧的项目。以下示例匹配“str1”或“str3”。
    
    [jerry]$ echo -e "str1\nstr2\nstr3\nstr4" | sed -n '/str\(1\|3\)/ p' 
    
    执行上面的代码,你会得到以下结果:
    
    str1 
    str3
    
    请注意,括号和竖线 (|) 的对被“\”字符转义。
  • 转义字符

    有一些特殊字符。比如换行用“\n”表示,回车用“\r”表示,以此类推。要将这些字符用于常规 ASCII 上下文,我们必须使用反斜杠 (\) 字符对它们进行转义。本章说明特殊字符的转义。

    转义“\”

    以下示例匹配模式“\”。
    
    [jerry]$ echo 'str1\str2' | sed -n '/\\/ p'
    
    执行上面的代码,你会得到以下结果:
    
    str1\str2 
    

    转义“\n”

    以下示例匹配换行符。
    
    [jerry]$ echo 'str1\nstr2' | sed -n '/\\n/ p'
    
    执行上面的代码,你会得到以下结果:
    
    str1\nstr2
    

    转义“\r”

    以下示例匹配回车符。
    
    [jerry]$ echo 'str1\rstr2' | sed -n '/\\r/ p'
    
    执行上面的代码,你会得到以下结果:
    
    str1\rstr2
    

    转义“\dnnn”

    这匹配十进制 ASCII 值为“nnn”的字符。以下示例仅匹配字符“a”。
    
    [jerry]$ echo -e "a\nb\nc" | sed -n '/\d97/ p'
    
    执行上面的代码,你会得到以下结果:
    
    a
    

    转义“\onnn”

    这匹配八进制 ASCII 值为“nnn”的字符。以下示例仅匹配字符“b”。
    
    [jerry]$ echo -e "a\nb\nc" | sed -n '/\o142/ p' 
    
    执行上面的代码,你会得到以下结果:
    
    b 
    
    这匹配十六进制 ASCII 值为“nnn”的字符。以下示例仅匹配字符“c”。
    
    [jerry]$ echo -e "a\nb\nc" | sed -n '/\x63/ p'
    
    执行上面的代码,你会得到以下结果:
    
    c
    
  • 正则表达式的 POSIX 类

    有一些保留字有特殊的含义。这些保留字被称为正则表达式的 POSIX 类。本节介绍 SED 支持的 POSIX 类。

    [:铝:]

    它暗示字母和数字字符。以下示例仅匹配“One”和“123”,但不匹配制表符。
    
    [jerry]$ echo -e "One\n123\n\t" | sed -n '/[[:alnum:]]/ p'
    
    执行上面的代码,你会得到以下结果:
    
    One 
    123
    

    [:α:]

    它仅暗示字母字符。以下示例仅匹配单词“One”。
    
    [jerry]$ echo -e "One\n123\n\t" | sed -n '/[[:alpha:]]/ p'
    
    执行上面的代码,你会得到以下结果:
    
    One 
    

    [:空白的:]

    它意味着可以是空格或制表符的空白字符。以下示例仅匹配制表符。
    
    [jerry]$ echo -e "One\n123\n\t" | sed -n '/[[:space:]]/ p' | cat -vte
    
    执行上面的代码,你会得到以下结果:
    
    ^I$
    
    请注意,命令“cat -vte”用于显示制表符 (^I)。

    [:数字:]

    它仅暗示十进制数字。以下示例仅匹配数字“123”。
    
    [jerry]$ echo -e "abc\n123\n\t" | sed -n '/[[:digit:]]/ p' 
    
    执行上面的代码,你会得到以下结果:
    
    123 
    

    [:降低:]

    它仅暗示小写字母。以下示例仅匹配“一个”。
    
    [jerry]$ echo -e "one\nTWO\n\t" | sed -n '/[[:lower:]]/ p' 
    
    执行上面的代码,你会得到以下结果:
    
    one 
    

    [:上:]

    它仅暗示大写字母。以下示例仅匹配“TWO”。
    
    [jerry]$ echo -e "one\nTWO\n\t" | sed -n '/[[:upper:]]/ p'
    
    执行上面的代码,你会得到以下结果:
    
    TWO
    

    [:观点:]

    它暗示包含非空格或字母数字字符的标点符号
    
    [jerry]$ echo -e "One,Two\nThree\nFour" | sed -n '/[[:punct:]]/ p'
    
    执行上面的代码,你会得到以下结果:
    
    One,Two
    

    [:空间:]

    它暗示空白字符。以下示例说明了这一点。
    
    [jerry]$ echo -e "One\n123\f\t" | sed -n '/[[:space:]]/ p' | cat -vte 
    
    执行上面的代码,你会得到以下结果:
    
    123^L^I$ 
    
  • 元字符

    与传统的正则表达式一样,SED 也支持元字符。这些是 Perl 风格的正则表达式。请注意,元字符支持是特定于 GNU SED 的,可能不适用于 SED 的其他变体。让我们详细讨论元字符。
  • 字边界 (\b)

    在正则表达式术语中,“\b”匹配单词边界。例如,“\bthe\b”匹配“the”,但不匹配“these”、“there”、“they”、“then”等。以下示例说明了这一点。
    
    [jerry]$ echo -e "these\nthe\nthey\nthen" | sed -n '/\bthe\b/ p'
    
    执行上面的代码,你会得到以下结果:
    
    the
    
  • 非字边界 (\B)

    在正则表达式术语中,“\B”匹配非单词边界。例如,“the\B”匹配“这些”和“他们”,但不匹配“the”。以下示例说明了这一点。
    
    [jerry]$ echo -e "these\nthe\nthey" | sed -n '/the\B/ p'
    
    执行上面的代码,你会得到以下结果:
    
    these 
    they
    
  • 单个空格 (\s)

    在 SED 中,“\s”表示单个空格字符。以下示例匹配“Line\t1”但不匹配“Line1”。
    
    [jerry]$ echo -e "Line\t1\nLine2" | sed -n '/Line\s/ p'
    
    执行上面的代码,你会得到以下结果:
    
    Line 1 
    
  • 单个非空白 (\S)

    在 SED 中,“\S”表示单个空格字符。以下示例匹配“Line2”但不匹配“Line\t1”。
    
    [jerry]$ echo -e "Line\t1\nLine2" | sed -n '/Line\S/ p' 
    
    执行上面的代码,你会得到以下结果:
    
    Line2
    
  • 单字字符 (\w)

    在 SED 中,“\w”表示单个单词字符,即字母字符、数字和下划线 (_)。以下示例说明了这一点。
    
    [jerry]$ echo -e "One\n123\n1_2\n&;#" | sed -n '/\w/ p'
    
    执行上面的代码,你会得到以下结果:
    
    One 
    123 
    1_2
    
  • 单个非单词字符 (\W)

    在 SED 中,“\W”表示与“\w”完全相反的单个非单词字符。以下示例说明了这一点。
    
    [jerry]$ echo -e "One\n123\n1_2\n&;#" | sed -n '/\W/ p'
    
    执行上面的代码,你会得到以下结果:
    
    &;#
    
  • 模式空间的开头 (\`)

    在 SED 中,“\`”表示模式空间的开始。以下示例仅匹配单词“One”。
    
    [jerry]$ echo -e "One\nTwo One" | sed -n '/\`One/ p' 
    
    执行上面的代码,你会得到以下结果:
    
    One