ruby-on-rails
  • ruby
  • 2013-04-11 3 views 0 likes 
    0

    Как решить следующую проблему?Ruby заменяет только точную строку соответствия другой строкой

    У меня есть HTML строку как следующий:

    <p>aaa, b aa aaaaa?<br/>Next possible text b bb aa b.</p> 
    

    Теперь я хотел бы заменить, например, только

    "aaa" 
    

    с

    "<div class='special'>aaa</div>" 
    

    новую строку после замены:

    <p><div class='special'>aaa</div>, b aa aaaaa?<br/>Next possible text b bb aa b.</p> 
    

    Итак, я хотел бы использовать общий заменитель, который заменяет только точную строку соответствия. «aaa» был всего лишь примером. Это может быть также «bb» или «two words» (=> два слова, поэтому text.split не будет работать, на мой взгляд).

    У кого-нибудь есть идея для такой динамичной находки, соответствия и замены?

    Я попробовал это уже, как следующее:

    items = ["aaa", "a", "aa", "aa b", "c"] 
    text = "<p>aaa, b aa aaaaa?<br/>Next possible text b bb aa b.</p>" 
    words = text.split => ["<p>aaa,", "b", "aa", "aaaaa?<br/>Next", "possible", "text", "b", "bb", "aa", "b.</p>"] 
    new_words = [] 
    
    words.each do |w| 
        items.each do |item| 
        if w == item 
         w = '<div class="special">#{item}</div>' 
        end 
        end 
        new_words << w 
    end 
    text = new_words.join(" ") 
    

    Результат:

    "<p>aaa, b <div class='special'>aa</div> aaaaa?<br/>Next possible text b bb <div class='special'>aa</div> b.</p>" 
    

    Но это должно быть:

    "<p><div class='special'>aaa</div>, b <div class='special'>aa</div> aaaaa?<br/>Next possible text b bb <div class='special'>aa b</div>.</p>" 
    

    моих самых больших проблем являются:

    • специальные символы, такие как «?()% €» -характеры в конце строки => „ааа“, из примера
    • подстрок с теми же частями => как „ааа“ и „аа“
    • Два слова, как один пункт => как «аа Ь» из примера

    Кто-то идея для фиксации мои проблемы?

    EDIT: что-то только заполнитель для моей замены .. моя реальная замена также может быть:

    %Q(<dfn title="#{strip_tags item.text}">#{item.name}</dfn>) 
    

    item.text может быть все => может содержать также «ааа» item.name для пример «aaa»

    Таким образом, множественный gsub заменит также уже замененное содержимое.

    ответ

    1

    Я бы использовал регулярное выражение, Rubular - отличное место для изучения и тестирования ваших выражений. Для получения дополнительной информации о том, как использовать gsub, проверьте Jayfields Blog post. Это может не соответствовать всем вашим случаям использования для этой проблемы, поэтому вам может потребоваться изменить его.

    str.gsub /^<p>a{3}/, "<div class='special'>aaa</div>" 
    
    
        What this says is starting at the beginning of the string (^) 
        find <p> and 3 assurances of the letter a. 
    
    +0

    Это должно быть 'sub' not' gsub', поскольку OP хочет только первое совпадение и не указывает, что он всегда будет рядом с тегом. – iain

    2

    Вы ищете String#sub (не gsub)

    s = "<p>aaa, b aa aaaaa?<br/>Next possible text b bb aa b.</p>" 
    # => "<p>aaa, b aa aaaaa?<br/>Next possible text b bb aa b.</p>" 
    match = "aaa" 
    # => "aaa" 
    replacement = "<div class='special'>aaa</div>" 
    # => "<div class='special'>aaa</div>" 
    s.sub match, replacement 
    # => "<p><div class='special'>aaa</div>, b aa aaaaa?<br/>Next possible text b bb aa b.</p>" 
    "<p><div class='special'>aaa</div>, b aa aaaaa?<br/>Next possible text b bb aa b.</p>" == _ 
    # => true 
    
    +0

    , но если строка «

    aaa, b aa aaaaa?
    Следующий возможный текст b bb aa b.aaa.

    « Это не сработает? – Mattherick

    +0

    Это не сработает * если вы сохранили содержимое переменной * 'match' * одинаково. * Если у вас есть другая строка, вы можете либо изменить переменную' match', либо через 'match =" b bb "' (или что бы это ни было в строке, которую вы хотите сопоставить), или, возможно, лучше отредактируйте свой вопрос и сообщите нам, как изменяются строки и как вы знаете, какую часть захватить. – iain

    -1

    Вот метод Заменитель вы хотите (с использованием GSUB, конечно):

    def replacer(orig,pattern,replace) 
        orig.gsub(/#{pattern}(\s|\.|,)/,replace+'\1').to_s 
    end 
    
    2.0.0dev :001 > def replacer(orig,pattern,replace) 
    2.0.0dev :002?>  orig.gsub(/#{pattern}(\s|\.|,)/,replace+'\1').to_s 
    2.0.0dev :003?> end 
    => nil 
    2.0.0dev :004 > replacer("<p>aaa, b aa aaaaa?<br/>Next possible text b bb aa b.</p>", "aaa", "<div class='special'>aaa</div>") 
    => "<p><div class='special'>aaa</div>, b aa aaaaa?<br/>Next possible text b bb aa b.</p>" 
    
    2

    Это не ясно, будет ли существует один экземпляр aaa или несколько, и хотите ли вы, чтобы все они были заменены, или только первый.

    Это заменит только первое:

    text = "<p>aaa, b aa aaaaa?<br/>Next possible text b bb aa b.</p>" 
    text.sub(/\b(aaa)\b/, %q"<div class='special'>\1</div>") 
    => "<p><div class='special'>aaa</div>, b aa aaaaa?<br/>Next possible text b bb aa b.</p>" 
    

    Это заменит все вхождения:

    text = "<p>aaa, b aa aaaaa?<br/>Next possible text b bb aa b.</p>" * 2 
    => "<p>aaa, b aa aaaaa?<br/>Next possible text b bb aa b.</p><p>aaa, b aa aaaaa?<br/>Next possible text b bb aa b.</p>" 
    
    text.gsub(/\b(aaa)\b/, %q"<div class='special'>\1</div>") 
    => "<p><div class='special'>aaa</div>, b aa aaaaa?<br/>Next possible text b bb aa b.</p><p><div class='special'>aaa</div>, b aa aaaaa?<br/>Next possible text b bb aa b.</p>" 
    

    Вы можете поместить "aaa" в переменную и найти интерполяцией этой цели в схеме:

    target = 'aaa' 
    text.gsub(/\b(#{ target })\b/, %q"<div class='special'>\1</div>") 
    => "<p><div class='special'>aaa</div>, b aa aaaaa?<br/>Next possible text b bb aa b.</p><p><div class='special'>aaa</div>, b aa aaaaa?<br/>Next possible text b bb aa b.</p>" 
    

    Регулярные выражения имеют \b (word-break), который позволяет легко определять слова или подстроки. Вы также можете заменить "aaa" несколькими словами.

    Смежные вопросы