Replace all non capitalised words with ruby

I would like to replace all non capitalised words in a text with "-".length of the word.

For instance I have the following Text (German):

Florian Homm wuchs als Sohn des mittelständischen Handwerksunternehmers Joachim Homm und seiner Frau Maria-Barbara „Uschi“ Homm im hessischen Bad Homburg vor der Höhe auf. Sein Großonkel mütterlicherseits war der Unternehmer Josef Neckermann. Nach einem Studium an der Harvard University, das er mit einem Master of Business Administration an der Harvard Business School abschloss, begann Homm seine Tätigkeit in der US-amerikanischen Finanzwirtschaft bei der Investmentbank Merrill Lynch, danach war er bei dem US-Fondsanbieter Fidelity Investments, der Schweizer Privatbank Julius Bär und dem US-Vermögensverwalter Tweedy Browne....

should be transformed into

Florian Homm ---- --- Sohn --- ------------ Handwerksunternehmers Joachim Homm --- ------ Frau Maria-Barbara „Uschi“ Homm -- ---------- Bad Homburg --- Höhe ---. ....


ANSWERS:


▶ input.gsub(/\p{L}+/) { |m| m[0] != m[0].upcase ? '-'*m.length : m }
#⇒ "Florian Homm ----- --- Sohn --- ------------------ Handwerksunternehmers..."

More clean solution (credits to Cary):

▶ input.gsub(/(?<!\p{L})\p{Lower}+(?!\p{L})/) { |m| '-' * m.length }

Try something like this

s.split.map { |word| ('A'..'Z').include?(word[0]) ? word : '-' * word.length }.join(' ')

You can try something like this for small input size:

Basically, I:

  1. Split the input string on whitespace character
  2. Map the array to either the word itself (if not capitalized) or the word replaced with dashes (if capitalized)
  3. join with whitespaces.

Like so

s = "Florian Homm wuchs als Sohn des mittelständischen Handwerksunternehmers Joachim Homm und seiner Frau Maria-Barbara „Uschi“ Homm im hessischen Bad Homburg vor der Höhe auf. Sein Großonkel mütterlicherseits war der Unternehmer Josef Neckermann. Nach einem Studium an der Harvard University, das er mit einem Master of Business Administration an der Harvard Business School abschloss, begann Homm seine Tätigkeit in der US-amerikanischen Finanzwirtschaft bei der Investmentbank Merrill Lynch, danach war er bei dem US-Fondsanbieter Fidelity Investments, der Schweizer Privatbank Julius Bär und dem US-Vermögensverwalter Tweedy Browne...."

s.split(/[[:space:]]/).map { |word| word.capitalize == word ? word : '-' * word.length }.join(' ')

Does that apply to your problem?

Cheers!

Edit: For a more memory efficient solution you can use regex replace gsub, check out this other answer by mudasobwa


r = /
    (?<![[:alpha:]]) # do not match a letter (negative lookbehind)      
    [[:lower:]]      # match a lowercase letter
    [[:alpha:]]*     # match zero or more letters
    /x               # free-spacing regex definition mode

str = "Frau Maria-Barbara „Uschi“ Homm im hessischen Bad Homburg vor der Höhe auf."

str.gsub(r) { |m| '-'*m.size }
  #=> "Frau Maria-Barbara „Uschi“ Homm -- ---------- Bad Homburg --- --- Höhe ---."
"die Richter/-innen".gsub(r) { |m| '-'*m.size }
  #=> "--- Richter/------" 
"Jede(r) Anwältin und Anwalt".gsub(r) { |m| '-'*m.size }
  #=> "Jede(-) Anwältin --- Anwalt" 

Solution

This problem is harder than it looks!

This code might be more memory hungry than others, but I dare say it works for a wider range of (weird) German words :

def hide_non_capitalized(text)
  text.split(/[[:space:]]/).map do |chars|
    first_letter = chars[/[[:alpha:]]/]
    if first_letter && first_letter == first_letter.downcase
      ## Keep non-letters :
      chars.gsub(/[[:alpha:]]/,'-')
      ## Replace every character :
      # '-' * chars.size
    else
      chars
    end
  end.join(' ')
end

It splits the text into character blocks, and replaces all the letters of a block if its first letter is lowercase. This code requires Ruby 2.4, because 'ä'.upcase is still 'ä' up to Ruby 2.3.

Test

puts hide_non_capitalized(text)
#=> Florian Homm ----- --- Sohn --- ----------------- Handwerksunternehmers Joachim Homm --- ------ Frau Maria-Barbara „Uschi“ Homm -- ---------- Bad Homburg --- --- Höhe ---. Sein Großonkel ----------------- --- --- Unternehmer Josef Neckermann. Nach ----- Studium -- --- Harvard University, --- -- --- ----- Master -- Business Administration -- --- Harvard Business School ---------, ------ Homm ----- Tätigkeit -- --- US-amerikanischen Finanzwirtschaft --- --- Investmentbank Merrill Lynch, ------ --- -- --- --- US-Fondsanbieter Fidelity Investments, --- Schweizer Privatbank Julius Bär --- --- US-Vermögensverwalter Tweedy Browne....

hide_none = "Änderung. „Uschi“, Attaché-case Maria-Barbara US-Fondsanbieter. Die Richter/-innen. Jede(r) 1234 \"#+?\""
puts hide_non_capitalized(hide_none)
#=> Änderung. „Uschi“, Attaché-case Maria-Barbara US-Fondsanbieter. Die Richter/-innen. Jede(r) 1234 "#+?"


hide_all = "öfters. „word“ lowercase-Uppercase jede(r) not/exactly/a/word"
puts hide_non_capitalized(hide_all)
#=> ------. „----“ ------------------- ----(-) ---/-------/-/----


 MORE:


 ? Capitalize ALL words in a triple String
 ? Ruby - remove underscores and capitalize
 ? How do I make the first letter of a string uppercase in JavaScript?
 ? How do I make the first letter of a string uppercase in JavaScript?
 ? How do I make the first letter of a string uppercase in JavaScript?
 ? How do I make the first letter of a string uppercase?
 ? How do I make the first letter of a string uppercase?
 ? How do I make the first letter of a string uppercase?
 ? How do I make the first letter of a string uppercase in JavaScript?
 ? How do I capitalize the first letter of each text input in javaScript?