2013-06-17 2 views
2

Я пытаюсь сопоставить некоторые строки в текстовом файле с регулярным выражением, а затем изменить все места, где найден шаблон. Это похоже на поиск и замену, но я пытаюсь заменить измененной версией того, что было найдено (и я уверен, что у этого есть имя, но я недостаточно знаком с ним).Изменение совпадений регулярных выражений в заменах

Поэтому я ищу для строк, которые соответствуют [a-z]_[a-z] (например, some_string), и я хочу, чтобы заменить его, удалив подчеркивание и прописных буквы второго нижнего регистра слова, по существу верблюда кожухотрубного его (someString).

Любые указатели на то, как это сделать (сложная часть, я не знаю, как это сделать даже для Google).

Редактировать

Я пытался упрощать вопрос немного, чтобы сделать его более универсальным, но я также пытаюсь сделать это только в том случае, если матч не происходит в кавычках. То есть, я не хочу сопоставлять символы подчеркивания в кавычках (так что здесь нет совпадения: "this_is_a_string" ... это должно оставаться как есть). Вероятно, я должен был включить это, когда я впервые сделал этот пост.

+0

Вы хотите изучить обратные ссылки. Создайте два или более регулярных выражения, которые вместе совпадают с первым, а затем вы можете использовать обратную ссылку одного из них, чтобы изменить его. – Leeish

+0

@jbrennan Я считаю, что делать это с родными строками будет проще, чем слова массива = indexOf ('-'). Split; слова [1] .charAt (1) .upperCase; words.join ^^^ psuedocode – raam86

+1

@ raam86 Я подумал об этом, но у меня есть еще одно требование, при котором under_scores могут быть сопоставлены только в том случае, если они не в кавычках, поэтому регулярное выражение немного сложнее, чем показанное мной. – jbrennan

ответ

4

вы можете использовать функцию обратного вызова с GSUB, например:

"some_thing_good".gsub(/_([a-z])/) {|m| m[1].upcase} 

Чтобы избежать строк внутри двойных кавычек вы можете сделать это:

"\"look_at_me\" some_thing_good".gsub(/"[^"]+"|_[a-z]/) {|m| (m.length>2)? m : m[1].upcase } 

Идея заключается в том, чтобы соответствовать их перед и заменить их на себя. Если я проверяю длину совпадения, я точно знаю, какая часть чередования была сопоставлена, так как вторая часть содержит только 2 символа, а первая часть - не менее 3 символов.

+0

Ага, это хорошо работает.Поэтому я не упомянул в своем вопросе, что мне также нужно исключать экземпляры, которые заключаются между кавычками. Знаете ли вы хороший способ сделать это? – jbrennan

+0

@jbrennan Вы можете сопоставить их сначала в чередовании и вернуть их, как это –

+0

вы можете подробно рассказать о том, что это значит? Я не уверен, что понимаю. – jbrennan

1

Я думаю, что лучший подход состоит в использовании заключать в круглые скобки шаблоны, которые вам интересны в

В вашем случае, я хотел бы использовать следующее регулярное выражение:.

string.gsub(/(?<=[a-z])_([a-z]+)/) {|s| "#{s[1].upcase}#{s[2..-1]}"} 

Это регулярное выражение может быть прочитан в двух частях, сначала попросите строку, которая начинается с действительного символа, а вторая за ней следует «_» и последовательность допустимых символов.

Внутри блока кода, вы можете использовать Regexp.last_match и возвращает MatchData, где вы можете получить доступ к каждому шаблону внутри скобок, например:

string.gsub(/(?<=[a-z])_([a-z]+)/) do |s| 
    p Regexp.last_match.to_a # this will print all sub-patterns found 
    "#{s[1].upcase}#{s[2..-1]}" # return formatted string 
end 

Как вы сказали, вы не интересны в шаблонах внутри кавычки. Я бы использовал регулярное выражение внутри другого. Первый для удаления котировки и второй для поиска узоров:

string.scan(/(\"[^\"]+\"|([^\"]+))/) do |s| 
    next s[0] unless s[1] # skip quoted data 
    # replace snake case to camel case 
    s[1].gsub(/(?<=[a-z])_([a-z]+)/) {|s| "#{s[1].upcase}#{s[2..-1]}"} 
end