Укороченная версия:
Мне довольно трудно понять два довольно сложных регулярных выражения в методе 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. /^(?:/(?=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
?
Извиняюсь за действительно длинный пост. Пожалуйста, укажите на мои ошибки в понимании двух регулярных выражений или объясните их лучше, если сможете.
Спасибо.