正则表达式

有些人在面对问题时,不经大脑便认为,“我知道,这里该用正则表达式”。现在他要面对两个问题了。

——Jamie Zawinski


  • 如果只是在字符串中进行简单的文本搜索,不要使用正则表达式,比如 string['text']
    [link]


  • 对于简单的构建操作,使用正则表达式作为索引即可。
    [link]

    1. match = string[/regexp/] # 获取匹配的内容
    2. first_group = string[/text(grp)/, 1] # 获取匹配的分组(grp)的内容
    3. string[/text (grp)/, 1] = 'replace' # string => 'text replace'

  • 当你不需要分组结果时,使用非捕获组。
    [link]

    1. # 差
    2. /(first|second)/
    3. # 好
    4. /(?:first|second)/

  • 避免使用 Perl 风格的、用以代表最近的捕获组的特殊变量(比如 $1$2 等)。使用 Regexp.last_match(n) 来替代。
    [link]

    1. /(regexp)/ =~ string
    2. ...
    3. # 差
    4. process $1
    5. # 好
    6. process Regexp.last_match(1)

  • 避免使用数字来获取分组。因为很难明白它们代表的含义。使用命名分组来替代。
    [link]

    1. # 差
    2. /(regexp)/ =~ string
    3. ...
    4. process Regexp.last_match(1)
    5. # 好
    6. /(?<meaningful_var>regexp)/ =~ string
    7. ...
    8. process meaningful_var

  • 在字符类别中,只有少数几个你需要特别关心的特殊字符:^-\],所以你不需要转义 [] 中的 . 与中括号。
    [link]


  • 小心使用 ^$ ,它们匹配的是一行的开始与结束,而不是字符串的开始与结束。如果你想要匹配整个字符串,使用 \A\z。(注意,\Z 实为 /\n?\z/)
    [link]

    1. string = "some injection\nusername"
    2. string[/^username$/] # 匹配成功
    3. string[/\Ausername\z/] # 匹配失败

  • 对于复杂的正则表达式,使用 x 修饰符。这种做法不但可以提高可读性,而且允许你加入必要的注释。注意的是,空白字符会被忽略。
    [link]

    1. regexp = /
    2. start # some text
    3. \s # white space char
    4. (group) # first group
    5. (?:alt1|alt2) # some alternation
    6. end
    7. /x

  • 对于复杂的替换,使用 sub/gsub 与哈希或区块组合的调用形式。
    [link]

    1. words = 'foo bar'
    2. words.sub(/f/, 'f' => 'F') # => 'Foo bar'
    3. words.gsub(/\w+/) { |word| word.capitalize } # => 'Foo Bar'