【问题标题】:ActiveSupport::Inflector::camelize - help in understanding regexActiveSupport::Inflector::camelize - 帮助理解正则表达式
【发布时间】:2014-01-04 21:41:51
【问题描述】:

短版:

我很难理解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 来自ActiveSupport::Inflector 模块中的Inflections 类,以及Inflections 类的initialize 方法,

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. /^(?:/(?=a)b/(?=\b|[A-Z_])|\w)/

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

虽然我认为它是 B。据我了解,(?: 提供不捕获的分组,(?= 表示正向前瞻断言,\b 在括号外匹配单词边界,在括号内匹配退格。因此,用英文术语来说,正则表达式 B 在与文本匹配时,会找到一个以 a 字符开头的字符串,然后是 b 字符,以及 (1. backspace [whatever that may mean] 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 调用完成后应用于整个字符串?

为这篇很长的帖子道歉。请指出我在理解这2个正则表达式方面的错误,或者如果可以的话,以更好的方式解释它们。

谢谢。

【问题讨论】:

  • 请让您的问题简明扼要。
  • @sawa,我可以对其进行编辑,使其变得非常简洁,但这会帮助那些查看问题的人了解我在理解 2 正则表达式方面的困难所在吗?我认为不会。
  • 无论如何我想我会添加一个 tldr 部分。

标签: ruby-on-rails ruby regex activesupport


【解决方案1】:

但是,我觉得奇怪的是传递 upper_case_first_letter = 骆驼化函数的错误应该导致它匹配一个字符串 从字符 ab 开始,因为那似乎不是 camelize 函数的行为方式。

?: 在这里就像. 一样,并且匹配字符串(即单个字符)但没有分组,因此匹配在$& 中。

既然 (?: 表示分组不捕获,那么 $1 的值是多少 当我们匹配_?还是_?

它是nil,因为没有捕获。值在$2

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-10-01
    • 1970-01-01
    • 2011-06-10
    相关资源
    最近更新 更多