ActiveSupport :: Inflector :: camelize - 帮助理解正则表达式

时间:2013-12-17 08:03:09

标签: ruby-on-rails ruby regex activesupport

简短版本:

我很难理解ActiveSupport::Inflector::camelize方法中两个相当复杂的正则表达式。

这是camelize方法的定义:

def camelize(term, uppercase_first_letter = true)
  string = term.to_s
  if uppercase_first_letter
    string = string.sub(/^[a-z\d]*/) { inflections.acronyms[$&] || $&.capitalize }
  else
    string = string.sub(/^(?:#{inflections.acronym_regex}(?=\b|[A-Z_])|\w)/) { $&.downcase }
  end
  string.gsub(/(?:_|(\/))([a-z\d]*)/i) { "#{$1}#{inflections.acronyms[$2] || $2.capitalize}" }.gsub('/', '::')
end

我有点难以理解:

string = string.sub(/^(?:#{inflections.acronym_regex}(?=\b|[A-Z_])|\w)/) { $&.downcase }

string.gsub(/(?:_|(\/))([a-z\d]*)/i) { "#{$1}#{inflections.acronyms[$2] || $2.capitalize}" }.gsub('/', '::')

请向我解释他们的意思。谢谢。

长版

这表明我试图理解正则表达式以及我如何解释它们的含义。如果你能够解决这个问题并纠正我的错误,将会非常有帮助。

对于第一个正则表达式

string = string.sub(/^(?:#{inflections.acronym_regex}(?=\b|[A-Z_])|\w)/) { $&.downcase }

根据我所看到的情况,inflections.acronym_regex来自Inflections模块中的ActiveSupport::Inflector类,以及initialize类的Inflections方法,

def initialize
  @plurals, @singulars, @uncountables, @humans, @acronyms, @acronym_regex = [], [], [], [], {}, /(?=a)b/
end

acronym_regex已分配/(?=a)b/。据我所知http://www.ruby-doc.org/core-2.0.0/Regexp.html#class-Regexp-label-Anchors

(?=pat) - Positive lookahead assertion: ensures that the following characters match pat, but doesn't include those characters in the matched text

所以/(?=a)b/确保字符a在文本中,但我们在匹配的文本中不包含字符a,字符a后面的字符必须是字符b。换句话说,"abc"会匹配此正则表达式,但"bbc"与此正则表达式不匹配,"abc"的匹配文本将为"b"(而不是"ab" })。

因此将inflections.acronym_regex的值合并到此正则表达式/^(?:#{inflections.acronym_regex}(?=\b|[A-Z_])|\w)/中,我不知道以下哪两个正则表达式结果:

一个。 /^(?:/(?=a)b/(?=\b|[A-Z_])|\w)/

B中。 /^(?:(?=a)b(?=\b|[A-Z_])|\w)/

虽然我认为它是B.根据我的理解,(?:提供分组而不捕获,(?=表示积极的先行断言,\b匹配字边界时外括号和匹配退格在括号内。所以在英语术语中,正则表达式B,当与文本匹配时,会找到一个以a字符开头的字符串,后跟一个b字符,以及(1. backspace中的一个) 2.任何大写字母或下划线3.任何英文字母,数字或下划线。

但是,我觉得奇怪的是,将upper_case_first_letter = false传递给camelize函数会导致它匹配以字符ab开头的字符串,因为这似乎不是如何camelize函数的行为。

对于第二个正则表达式

string.gsub(/(?:_|(\/))([a-z\d]*)/i) { "#{$1}#{inflections.acronyms[$2] || $2.capitalize}" }.gsub('/', '::')

正则表达式是:

/(?:_|(\/))([a-z\d]*)/i

我猜这个正则表达式将匹配以_/开头的子字符串,后跟0或更多(大写或小写的英文字母或数字)。此外,对于第一组(?:_|(\/)),无论我们是否匹配_/([a-z\d]*)捕获组将始终被视为第二组。我确实理解了块试图查找的部分inflections.acronyms[$2]并且在失败的情况下$2.captitalize

由于(?:表示没有捕获分组,因此$1匹配时_的值是多少?它还在_吗?对于.gsub('/', '::')部分,我猜测它会应用于初始gsub中的每个匹配,而不是在外部gsub调用完成后应用于整个字符串?< / p>

道歉真的很长的帖子。请指出我在理解2个正则表达式时的错误,或者如果你能做到的话,可以更好地解释它们。

谢谢。

1 个答案:

答案 0 :(得分:0)

  

然而,我觉得传递upper_case_first_letter =很奇怪   对camelize函数的false应该使它与字符串匹配   从字符ab开始,假设似乎不是   camelize函数的行为如何。

?:在这里的作用类似于.,并且匹配字符串(即单个字符),但没有分组,因此匹配位于$&

  

因为(?:表示没有捕获的分组,$ 1的值是多少   当我们匹配_?还在吗?

它是nil,因为没有捕获。该值位于$2

  

对于.gsub('/','::')部分,我猜它得到了   应用于初始gsub中的每个匹配,而不是应用   外部gsub调用完成后,整个字符串是什么?

它应用于整个结果gsub,块返回一个字符串,gsub('/', '::')在块之外。