AWK的入门学习记录之二——正则表达式

正则表达式

  • 正则表达式(regexp)是描述一组字符串的一种方法。因为正则表达式是awk编程的基本组成部分,所以它们的格式和用法应该单独一章讨论。
  • 用斜杠(“/”)括起来的正则表达式是一种awk模式,它匹配文本属于该集的每个输入记录。最简单的正则表达式是字母、数字或两者的序列。这样的regexp匹配包含该序列的任何字符串。因此,正则表达式'foo'匹配任何包含'foo'的字符串。因此,模式/foo/匹配任何包含记录中任意三个相邻字符'foo'的输入记录。其他类型的正则表达式允许您指定更复杂的字符串类。

1、如何使用正则表达式

  • 通过将正则表达式括在斜杠中,可以将其用作模式。然后针对每个记录的整个文本测试正则表达式。(通常,它只需要匹配文本的某些部分就可以成功。)例如,在字符串'li'出现在每个记录的任何位置时,打印记录的第二个字段:
    $ awk '/li/ { print $2 }' mail-list
    -| 555-5553
    -| 555-0542
    -| 555-6699
    -| 555-3430
    
  • 正则表达式也可以用于匹配表达式。这些表达式允许您指定要匹配的字符串;它不必是整个当前输入记录。两个运算符~!~执行正则表达式比较。使用这些运算符的表达式可以用作模式,也可以用在ifwhilefordo语句中。(参见Control Statements in Actions一节。)例如,如果表达式exp(作为字符串)与'regexp'匹配,则以下为真:
    exp ~ /regexp/
    
  • 此示例匹配或选择第一个字段中某处大写字母'J'的所有输入记录:
    $ awk '$1 ~ /J/' inventory-shipped
    -| Jan  13  25  15 115
    -| Jun  31  42  75 492
    -| Jul  24  34  67 436
    -| Jan  21  36  64 620
    
  • 下面例子同上效果一样:
    awk '{ if ($1 ~ /J/) print }' inventory-shipped
    
  • 如果表达式exp(作为字符串)与'regexp'不匹配,则下一个示例为true
    exp !~ /regexp/
    
  • 以下示例匹配或选择第一个字段不包含大写字母'J'的所有输入记录:
    $ awk '$1 !~ /J/' inventory-shipped
    -| Feb  15  32  24 226
    -| Mar  15  24  34 228
    -| Apr  31  52  63 420
    -| May  16  34  29 208
    …
    
  • 'regexp'用斜杠括起来时,比如/foo/,我们称它为regexp常量,就像5.27是数字常量,'foo'是字符串常量一样。

2、转义序列

  • 某些字符不能包含在字符串常量('foo')或正则表达式常量(/foo/)中。相反,它们应该用转义序列来表示,转义序列是以反斜杠('\')开头的字符序列。转义序列的一种用法是在字符串常量中包含双引号字符。由于纯双引号以字符串结尾,因此必须使用'\',将实际的双引号字符表示为字符串的一部分。例如:

    $ awk 'BEGIN { print "He said \"hi!\" to her." }'
    -| He said "hi!" to her.
    

    反斜杠字符本身是另一个通常不能包含的字符;必须写入'\\'才能在字符串或regexp中放入一个反斜杠。因此,内容为两个字符'"''\'的字符串必须写为"\”\\"

  • 下面的列表显示了awk中使用的所有转义序列以及它们所代表的内容。除非另有说明,所有这些转义序列都适用于字符串常量和regexp常量:

    • \\反斜杠'\'
    • \a警报字符Ctrl-gASCII码 7(BEL)。(这通常会发出某种声音。)
    • \b退格Ctrl-h, ASCII code 8 (BS)
    • \fFormfeed格式, Ctrl-l, ASCII code 12 (FF).
    • \n换行Ctrl-j, ASCII code 10 (LF).
    • \r回车Ctrl-m, ASCII code 13 (CR).
    • \tHorizontal TAB, Ctrl-iASCII code 9 (HT).
    • \vVertical TAB, Ctrl-k, ASCII code 11 (VT).
    • \nnn八进制值nnn,其中nnn表示'0''7'之间的1到3位数字。例如,ASCII ESC(转义)字符的代码是“\033”。
    • \xhh…十六进制值hh,其中hh表示十六进制数字序列('0'–'9',以及'A'–'F''a'–'f')。'\x'后面最多允许有两个数字。任何其他十六进制数字都被视为简单的字母或数字。(c.e.)(POSIX awk中不允许'\x'转义序列。)

3、正则表达式运算符

可以将正则表达式与特殊字符(称为正则表达式运算符或元字符)组合,以增强正则表达式的功能和多功能性。

1、awk中的Regexp运算符

前面在Escape Sequences中描述的转义序列在regexp中是有效的。它们由'\'引入,作为处理regexp的第一步被识别并转换为相应的实数字符。

下面是元字符列表。所有不是转义序列且未在此列出的字符都代表它们自己:

  • \: 这将抑制匹配时字符的特殊含义。例如,'\$'与字符'$'匹配。
  • ^:这与字符串的开头匹配。例如,'^@chapter'匹配字符串开头的'@chapter',并可用于标识Texinfo source files中的章节开头。'^'被称为锚定,因为它锚定模式以仅在字符串的开头匹配。重要的是要认识到'^'与嵌入字符串中的行首(换行符'\n'后面的点)不匹配。以下示例中的条件是not true
    if ("line1\nLINE 2" ~ /^L/) …
    
  • $:这类似于'^',但它只在字符串的末尾匹配。例如,'p$'匹配以'p'结尾的记录。'$'是一个锚点,与字符串中嵌入的行尾(换行符'\n'前的点)不匹配。以下示例中的条件是not true
    if ("line1\nLINE 2" ~ /1$/) …
    
  • 方法

4、有多少文本匹配?

5、使用动态regexp

'~''!~'运算符不必是regexp常量(即斜杠之间的字符串)。它可以是任何表达式。表达式被求值并在必要时转换为字符串;然后字符串的内容被用作regexp。以这种方式计算的regexp称为动态regexpcomputed regexp

BEGIN { digits_regexp = "[[:digit:]]+" }
$0 ~ digits_regexp    { print }

这会将digits_regexp设置为描述一个或多个数字的regexp,并测试输入记录是否与此regexp匹配。

当使用'~''!~'运算符,请注意用斜杠括起来的regexp常量和用双引号括起来的字符串常量之间有区别。如果要使用字符串常量,则必须了解字符串本质上是扫描两次的:第一次是在awk读取程序时,第二次是在操作符左侧的字符串与右侧的模式匹配时。这适用于任何字符串值表达式(如前一示例中所示的digits_regexp),而不仅仅是字符串常量。

你可能感兴趣的:(AWK,正则表达式,awk)