Упростить ряд операции со строками в Ruby


У меня есть ряд манипуляций строки, Я понимаю, что это с помощью следующего кода. Я хочу, чтобы быть более элегантным и читаемым, такой как стр.sub_heading().sub_codeblock()..., как я могу переписать мой код?

def sub_heading(str)
  str.gsub!(/^(#+)\w+/) {|m|  m.gsub("#", "=")}
  str.gsub!(/^(=+)(.+)/, '\1 \2 \1')
end

def sub_codeblock(str)
  str.gsub!(/```(.+\n)((.|\n)+)```/,  '{{{#!text_pygments \1\2}}}')
end

def sub_inlinecode(str)
  str.gsub!(/`(.+)`/, '{{{\1}}}')
end

def sub_bold(str)
  str.gsub!(/([^\w]|^)\*\*\w[\w\s\d\-_'"]*\*\*([^\w]|$)/) {|m|  m.gsub("**", "'''")}
end

def sub_italic(str)
  str.gsub!(/([^*]|^)\*\w[\w\s\d\-_'"]*\*([^*]|$)/) {|m|  m.gsub("*", "''")}
end

def sub_link(str)
  str.gsub!(/\[\[(.+)\|(.+)\]\]/, '[[\2|\1]]')
end

sub_heading(inputdata)
sub_codeblock(inputdata)
sub_inlinecode(inputdata)
sub_bold(inputdata)
sub_italic(inputdata)
sub_link(inputdata)


242
2
задан 12 декабря 2011 в 01:12 Источник Поделиться
Комментарии
2 ответа

Вы можете получить замены в хэш и называть их на другие.

replacements = { 
/1/ => ' one ',
/2/ => ' two ',
/([34])/ => ' (\1 is three or four) ',
}

test = '123'
replacements.each{|regex, repl|
test.gsub!(regex, repl)
}
p test

В gsub-версия с блоками нужна маленькая хитрость:

replacements = { 
/1/ => ' one ',
/2/ => ' two ',
/3/ => Proc.new{|m| m*2},
}

test = '123'
replacements.each{|regex, repl|
if repl.is_a?(Proc)
test.gsub!(regex){|m| repl.call(m)}
else
test.gsub!(regex, repl)
end
}
p test

В вашем случае вы можете определить свой замены:

Replacements = {
# sub_heading
/^(#+)\w+/ => Proc.new{|m| m.gsub("#", "=")},
/^(=+)(.+)/ => '\1 \2 \1',
# sub_codeblock
/```(.+\n)((.|\n)+)```/ => '{{{#!text_pygments \1\2}}}',
# sub_inlinecode
/`(.+)`/ => '{{{\1}}}',
# sub_bold
/([^\w]|^)\*\*\w[\w\s\d\-_'"]*\*\*([^\w]|$)/ => Proc.new{|m| m.gsub("**", "'''")},
# sub_italic
/([^*]|^)\*\w[\w\s\d\-_'"]*\*([^*]|$)/ => Proc.new{|m| m.gsub("*", "''")},
# sub_link
/\[\[(.+)\|(.+)\]\]/ => '[[\2|\1]]',
}

def my_replace(inputstring)
Replacements.each{|regex, repl|
if repl.is_a?(Proc)
inputstring.gsub!(regex){|m| repl.call(m)}
else
inputstring.gsub!(regex, repl)
end
}
end

my_replace(inputdata)

1
ответ дан 12 декабря 2011 в 10:12 Источник Поделиться


Я хочу, чтобы быть более элегантным и читаемым, таких как
ул. sub_heading().sub_codeblock()


  1. Если вы хотите вызвать непосредственно на объект String, вы должны открыть класс и добавить методы.

  2. Если вы хотите "ул. метод1.метода Method2...". (это правильный подход) вы не должны использовать такие методы, как суб!. Так:

    class String
    def sub_heading(str)
    gsub(/^(#+)\w+/) { |m| m.gsub("#", "=") }.
    gsub(/^(=+)(.+)/, '\1 \2 \1')
    end

    ....
    end


Вы получаете идею для других.

Однако, я woulnd не открыть стандартный класс, чтобы добавить такие специфические функции, написать класс-способ с этим всегда (помните: создавать новые строки, не обновление).

1
ответ дан 14 декабря 2011 в 01:12 Источник Поделиться