【发布时间】: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