Ruby on Rails PL Forum

Forum po¶więcone Ruby on Rails i językowi programowania Ruby

Nie jeste¶ zalogowany.

#1 2006-05-31 12:32:54

p_ch
Obserwator
Zarejestrowany: 2006-05-12
Posty: 31

Zamiana pojedynczych znaków

Witam,

Wiem, że problem jest pewnie lamerski, ale brakuje mi trochę obycia z Rubym ;-)

Potrzebuję zamienić wszystkie polskie znaki (±ęłóńżĽć) na ich odpowiedniki w ASCII (aelonzzc). W php mogłem sobie zrobić tak:

Kod: php

  1. $polish = array('±', 'ę', '¶', 'ć', 'ż', 'Ľ', 'ó', 'ł', 'ń', 'ˇ', 'Ę', '¦', 'Ć', 'Ż', '¬', 'Ó', 'Ł', 'Ń');
  2. $replace = array('a', 'e', 's', 'c', 'z', 'z', 'o', 'l', 'n', 'A', 'E', 'S', 'C', 'Z', 'Z', 'O', 'L', 'N');
  3. $url = str_replace($polish, $replace, $url);

Jak podobn± operację wykonać w Rubym (łańcuchy mam zapisane w UTF-8)? Próbowałem kombinować z tr(), ale kod:

Kod: ruby

  1. slug = "ę± ±ę dupa"
  2. slug = slug.tr('±', 'a')
  3. slug = slug.tr('ę', 'e')

daje mi jakie¶ dziwne wyniki neutral  (dostaję: aeaa aaae dupa)


pozdrawiam,
Piotr

Offline

 

#2 2006-05-31 12:46:39

RubyOnRails
Obserwator
Zarejestrowany: 2006-02-01
Posty: 47

Re: Zamiana pojedynczych znaków

http://wiki.rubyonrails.com/rails/pages … odeStrings lub zaczekaj około dwóch lat na wersję drug± Rubiego.

Offline

 

#3 2006-05-31 12:48:02

p_ch
Obserwator
Zarejestrowany: 2006-05-12
Posty: 31

Re: Zamiana pojedynczych znaków

Bez przesady, powinno jako¶ dać się to rozwi±zać ;-) PHP ma jeszcze gorsz± obsługę unikodu, a jako¶ sobie można z tym poradzić.


pozdrawiam,
Piotr

Offline

 

#4 2006-05-31 12:59:42

Adamh
Bywalec
Od: Warszawa
Zarejestrowany: 2006-01-15
Posty: 233
Serwis

Re: Zamiana pojedynczych znaków

Kod: ruby

  1. "jakie¶ słowo z ¶".gsub(/¶/, "s")

Offline

 

#5 2006-05-31 13:30:48

hipertracker
Administrator
Od: Irlandia
Zarejestrowany: 2006-01-10
Posty: 205
Serwis

Re: Zamiana pojedynczych znaków

p_ch napisał:

Jak podobn± operację wykonać w Rubym (łańcuchy mam zapisane w UTF-8)? Próbowałem kombinować z tr()

Z tr() nie masz co kombinować bo to działa na stringach 8 bitowych. W PHP też ci by ta funkcja nie zadziałała. Aby użyć tr() musisz wpierw string przekonwertować do jakiego¶ formatu 8 bitowego. Np.:

Kod: ruby

  1. require 'iconv'
  2.  
  3. def pl2ascii(s)
  4. ascii = "acelnoszzACELNOSZZ"
  5. cep = "\271\346\352\263\361\363\234\277\237\245\306\312\243\321\323\214\257\217"
  6. s = Iconv.new("cp1250", "UTF-8").iconv(s)
  7. s.tr!(cep,ascii)
  8. end
  9.  
  10. puts pl2ascii('zażółć gę¶l± jaĽń ZAŻÓŁĆ GʦLˇ JA¬Ń') # => zazolc gesla jazn ZAZOLC GESLA JAZN
  11.  
  12. =begin
  13.  
  14. Do generacji stringa z kodami cep1250 użyłem Pythona:
  15.  
  16. pl = [oct(ord(c)) for c in unicode('±ćęłń󶿼ˇĆĘŁŃӦݬ', 'utf8').encode('cp1250')]
  17. print ''.join(["\\%s" % c[1:] for c in pl])
  18. # => \271\346\352\263\361\363\234\277\237\245\306\312\243\321\323\214\257\217
  19.  
  20. =end

Oczywi¶cie, powyższy kod się wysypie jak masz w tek¶cie jakie¶ niekonwertowalne znaki z utf8 do cp1250.

Ostatnio edytowany przez jzabiello (2006-05-31 15:11:11)

Offline

 

#6 2006-05-31 13:42:41

p_ch
Obserwator
Zarejestrowany: 2006-05-12
Posty: 31

Re: Zamiana pojedynczych znaków

OK. Dzięki za odpowiedzi.

Mam jeszcze jedn± w±tpliwo¶ć. Przegl±dam sobie kod Typo, żeby zobaczyć jak zrealizowana jest tam zamiana tytułu na permalink. Je¶li tytuł brzmi: "Zażółć gę¶l± jaĽń", to permalink będzie taki: "zażółć-gę¶l±-jaĽń". Typo korzysta z takiego kodu:

Kod: ruby

  1. class String
  2. # Converts a post title to its-title-using-dashes
  3. # All special chars are stripped in the process
  4. def to_url
  5. return if self.nil?
  6. result = self.downcase
  7.  
  8. # replace quotes by nothing
  9. result.gsub!(/['"]/, '')
  10. # strip all non word chars
  11. result.gsub!(/\W/, ' ')
  12. # replace all white space sections with a dash
  13. result.gsub!(/\ +/, '-')
  14. # trim dashes
  15. result.gsub!(/(-)$/, '')
  16. result.gsub!(/^(-)/, '')
  17. result
  18. end
  19. end

Gdy próbuję ten sam kod zastosować u siebie:

Kod: ruby

  1. slug = link.title.downcase
  2. slug.gsub!(/['"]/, '')
  3. # strip all non word chars
  4. slug.gsub!(/\W/, ' ')
  5. # replace all white space sections with a dash
  6. slug.gsub!(/\ +/, '-')
  7. # trim dashes
  8. slug.gsub!(/(-)$/, '')
  9. slug.gsub!(/^(-)/, '')

to otrzymuję: "za-g-l-ja". Od czego to zależy?


pozdrawiam,
Piotr

Offline

 

#7 2006-05-31 14:34:34

pawel
Adept
Od: Krakow
Zarejestrowany: 2006-01-28
Posty: 155
Serwis

Re: Zamiana pojedynczych znaków

To z CodeSnippets: National characters to ascii letters. Moze sie przyda.


------------------------------------------------------------------------------------
Java Developers can produce Powerful + Complex  Web Applications ... slowly.

Offline

 

#8 2006-05-31 15:21:30

hipertracker
Administrator
Od: Irlandia
Zarejestrowany: 2006-01-10
Posty: 205
Serwis

Re: Zamiana pojedynczych znaków

Tu jest inna wersja, bardziej w Ruby-way. Wzbogaca wszystkie stringi o dodatkow± metodę.

Kod: ruby

  1. require 'iconv'
  2.  
  3. class String
  4. def to_ascii
  5. ascii = "acelnoszzACELNOSZZ"
  6. cep = "\271\346\352\263\361\363\234\277\237"
  7. s = Iconv.new("cp1250", "UTF-8").iconv(self)
  8. s.tr!(cep,ascii)
  9. end
  10. end
  11.  
  12. puts 'zażółć gę¶l± jaĽń'.to_ascii # => zazolc gesla jazn

Offline

 

#9 2006-05-31 16:13:25

pawel
Adept
Od: Krakow
Zarejestrowany: 2006-01-28
Posty: 155
Serwis

Re: Zamiana pojedynczych znaków

Ladnie, bo tyle gsubow mnie przerazalo smile Dodatkowo mozna latwo rozszerzyc o inne jezyki.

Dla przykladu podam jave. Uzywalem ibm-owskiej bibl icu4j.

Kod: java

  1. import com.ibm.icu.text.Transliterator;
  2.  
  3. public class TextUtils {
  4. static final String suplement = "ł>l;Ł>L;ß>ss";
  5. static final String accentID =
  6. "NFD; Suplement; [:Nonspacing Mark:] Remove; NFC";
  7. static final String loginID =
  8. "NFD; Suplement; [\\P{ASCII}\\P{Alpha}] Remove; Lower; NFC";
  9. // "Greek-Latin; Cyrillic-Latin; ru-en;"
  10. static TextUtils singleton = null;
  11. private TextUtils() {
  12. Transliterator.registerInstance(
  13. Transliterator.createFromRules("Any-Suplement",
  14. suplement, Transliterator.FORWARD));
  15. }
  16. public static TextUtils getInstance() {
  17. if (singleton == null) {
  18. singleton = new TextUtils();
  19. }
  20. return singleton;
  21. }
  22. public String transliterate(String customID, String text) {
  23. Transliterator acc = Transliterator.getInstance(customID);
  24. System.out.println(acc.getID());
  25. return acc.transliterate(text);
  26. }
  27. public String removeAccents(String text) {
  28. return transliterate(accentID, text);
  29. }
  30. public String prepare4LoginName(String text) {
  31. return transliterate(loginID, text);
  32. }
  33. public String prepare4LoginName(String text, int maxChars) {
  34. String s = transliterate(loginID, text);
  35. return s.length() > maxChars ? s.substring(0, maxChars) : s;
  36. }
  37. }


Jak widac nie do konca sobie transliterator radzil - stad suplement ... ale takie rozw. jest b. wydajne bo nie operuje na regexp.


------------------------------------------------------------------------------------
Java Developers can produce Powerful + Complex  Web Applications ... slowly.

Offline

 

#10 2006-05-31 17:01:53

p_ch
Obserwator
Zarejestrowany: 2006-05-12
Posty: 31

Re: Zamiana pojedynczych znaków

Kolejne lamerskie pytanie: jak podpi±ć ten skrypt do mojej aplikacji? smile

Zrobiłem tak: utworzyłem plik string_utils.rb w katalogu lib, z kodem podanym przez jzabiello. W environments.rb dodałem linię: require 'lib/string_utils'

No i gdy próbuję wywołać to_ascii to albo się pluje, że nie mógł wczytać iconv, albo że metoda nie istnieje. Webrick chce się uruchomić, gdy w environments.rb jest dodana przeze mnie linia.

Wiem, że to pewnie jedna z najprostszych rzeczy i najgłupszych błędów, ale Ruby jest ci±gle dla mnie czym¶ nowym. Szukałem w dokumentacji, ale nie znalazłem. Będę wdzięczny za pomoc.


pozdrawiam,
Piotr

Offline

 

#11 2006-05-31 17:27:43

pawel
Adept
Od: Krakow
Zarejestrowany: 2006-01-28
Posty: 155
Serwis

Re: Zamiana pojedynczych znaków

Dodaj samo require 'string_utlis' (bez lib).


------------------------------------------------------------------------------------
Java Developers can produce Powerful + Complex  Web Applications ... slowly.

Offline

 

#12 2006-05-31 19:58:05

p_ch
Obserwator
Zarejestrowany: 2006-05-12
Posty: 31

Re: Zamiana pojedynczych znaków

To samo. Może po prostu nie mam biblioteki iconv?


pozdrawiam,
Piotr

Offline

 

#13 2006-05-31 21:45:29

pawel
Adept
Od: Krakow
Zarejestrowany: 2006-01-28
Posty: 155
Serwis

Re: Zamiana pojedynczych znaków

Pod eclipse (RDT) dziala. Bibl. iconv jest standardowo w ruby. Prawdop. masz inny encoding pliku niz UTF-8.

Ja dostawalem Iconv::IllegalSequence dla cp1250 i iso8859-2.

Tego typu sprawy zniechecaja do Rubiego vs. Java czy Python.


------------------------------------------------------------------------------------
Java Developers can produce Powerful + Complex  Web Applications ... slowly.

Offline

 

#14 2006-05-31 21:53:51

hipertracker
Administrator
Od: Irlandia
Zarejestrowany: 2006-01-10
Posty: 205
Serwis

Re: Zamiana pojedynczych znaków

Pod windowsami standardowo nie ma ani iconv ani gettext. Trzeba to doinstalowac, np. st±d: http://sourceforge.net/project/showfile … _id=25167.

Offline

 

#15 2006-05-31 21:55:30

hipertracker
Administrator
Od: Irlandia
Zarejestrowany: 2006-01-10
Posty: 205
Serwis

Re: Zamiana pojedynczych znaków

p_ch napisał:

To samo. Może po prostu nie mam biblioteki iconv?

Uruchom irb i wpisz

Kod:

require 'iconv'

Jak zwróci true to masz zainstalowane.

Offline

 

#16 2006-05-31 23:24:53

p_ch
Obserwator
Zarejestrowany: 2006-05-12
Posty: 31

Re: Zamiana pojedynczych znaków

LoadError: No such file to load.

Czyli lipa.

W pełni zadowoliłoby mnie rozwi±zanie używane w typo do tworzenia permalinków (kod, który podałem kilka postów wyżej). Nie mam jednak pojęcia, dlaczego w Typo działa on normalnie, a u mnie usuwa wszystkie polskie znaki.


pozdrawiam,
Piotr

Offline

 

#17 2006-06-01 00:06:48

pawel
Adept
Od: Krakow
Zarejestrowany: 2006-01-28
Posty: 155
Serwis

Re: Zamiana pojedynczych znaków

Mysle, ze chodzi o wlaczenie multibyte support (tzn. dokladnie utf8) - typo ma to globalnie ustawione w envionment.rb

Kod: ruby

  1. $KCODE = 'u'
  2. require 'jcode'


Opcjonalnie mozesz wlaczyc dla danego wyr. regularnego

Kod: ruby

  1. expr = /[ˇ±]/u # to 'u' na koncu
  2. puts expr.kcode # => utf8

Kod: ruby

  1. # strip all non word chars
  2. result.gsub!(/\W/, ' ')


Powyzszy fragm. z typo pozbawial cie polskich znakow bo nie sa one "word char" w rozumieniu ASCII. /\W/u powinno zalatwic sprawe, ale i tak musisz pozniej podmienic diakrytyki - sprytna metoda zaproponowana przez Jarka Zabiello albo gsub-y z Code Snippets.

PS. Ja mam pod winda standardowo iconv (One-Click Installer, 1.8.4-16 release candidate 1)


------------------------------------------------------------------------------------
Java Developers can produce Powerful + Complex  Web Applications ... slowly.

Offline

 

#18 2006-06-01 09:49:13

p_ch
Obserwator
Zarejestrowany: 2006-05-12
Posty: 31

Re: Zamiana pojedynczych znaków

Dzięki, o to mi chodziło :-)

Teraz już ¶miga jak trzeba.


pozdrawiam,
Piotr

Offline

 

#19 2008-07-31 12:36:56

bober0
Obserwator
Od: Kraków
Zarejestrowany: 2007-11-14
Posty: 99
Serwis

Re: Zamiana pojedynczych znaków

jzabiello napisał:

Kod: ruby

  1. require 'iconv'
  2.  
  3. def pl2ascii(s)
  4. ascii = "acelnoszzACELNOSZZ"
  5. cep = "\271\346\352\263\361\363\234\277\237"
  6. s = Iconv.new("cp1250", "UTF-8").iconv(s)
  7. s.tr!(cep,ascii)
  8. end
  9.  
  10. puts pl2ascii('zażółć gę¶l± jaĽń') # => zazolc gesla jazn

jak unowocze¶nić ten kod, żeby przerabiał też duże polskie litery?

Ostatnio edytowany przez bober0 (2008-07-31 12:37:36)


Masz konto na workingwithrails.com? Poleć mnie
Prawn i prawnto - dlaczego jestem przeciw?

Offline

 

#20 2008-07-31 14:26:03

hipertracker
Administrator
Od: Irlandia
Zarejestrowany: 2006-01-10
Posty: 205
Serwis

Re: Zamiana pojedynczych znaków

bober0 napisał:

jzabiello napisał:

Kod: ruby

  1. require 'iconv'
  2.  
  3. def pl2ascii(s)
  4. ascii = "acelnoszzACELNOSZZ"
  5. cep = "\271\346\352\263\361\363\234\277\237"
  6. s = Iconv.new("cp1250", "UTF-8").iconv(s)
  7. s.tr!(cep,ascii)
  8. end
  9.  
  10. puts pl2ascii('zażółć gę¶l± jaĽń') # => zazolc gesla jazn

jak unowocze¶nić ten kod, żeby przerabiał też duże polskie litery?

Trzeba  dodać brakuj±ce kody, zobacz  poprawion± wersję

Offline

 

#21 2008-08-01 12:04:57

Tomash
RoR Guru
Zarejestrowany: 2007-04-01
Posty: 1721

Re: Zamiana pojedynczych znaków

Po przeczytaniu rozwi±zań Obiego i innych wypracowali¶my rozwi±zanie brutalne i brzydkie, ale skuteczne:

Kod: ruby

  1. class String
  2. def to_ascii_brutal
  3. #foo = self.downcase.strip
  4. foo = String.new(self)
  5. #foo = self.clone #.downcase.strip
  6. foo.gsub!(/[ˇÀ�?ÂÃ]/,'A')
  7. foo.gsub!(/[âäàãáäå�?ă±ǎǟǡǻ�?ȃȧẵặ]/,'a')
  8. foo.gsub!(/[Ę]/,'E')
  9. foo.gsub!(/[ëêéèẽēĕėẻȅȇẹȩęḙḛ�?ếễểḕḗệ�?]/,'e')
  10. foo.gsub!(/[Ì�?ÎĨ]/,'I')
  11. foo.gsub!(/[�?iìíîĩīĭïỉ�?ịįȉȋḭɨḯ]/,'i')
  12. foo.gsub!(/[ÒÓÔÕÖ]/,'O')
  13. foo.gsub!(/[òóôõ�?�?ȯö�?őǒ�?�?ơǫ�?ɵøồốỗổȱȫȭ�?�?ṑṓ�?ớỡởợǭộǿ]/,'o')
  14. foo.gsub!(/[ÙÚÛŨÜ]/,'U')
  15. foo.gsub!(/[ùúûũūŭüủůűǔȕȗưụṳųṷṵṹṻǖǜǘǖǚừứữửự]/,'u')
  16. foo.gsub!(/[ỳýŷỹȳ�?ÿỷẙƴỵ]/,'y')
  17. foo.gsub!(/[œ]/,'oe')
  18. foo.gsub!(/[ÆǼǢæ]/,'ae')
  19. foo.gsub!(/[Ń]/,'N')
  20. foo.gsub!(/[ñǹń]/,'n')
  21. foo.gsub!(/[ÇĆ]/,'C')
  22. foo.gsub!(/[çć]/,'c')
  23. foo.gsub!(/[ß]/,'ss')
  24. foo.gsub!(/[œ]/,'oe')
  25. foo.gsub!(/[ij]/,'ij')
  26. foo.gsub!(/[Ł]/,'L')
  27. foo.gsub!(/[�?ł]/,'l')
  28. foo.gsub!(/[¦]/,'S')
  29. foo.gsub!(/[]/,'s')
  30. foo.gsub!(/[¬Ż]/,'Z')
  31. foo.gsub!(/[Ľż]/,'z')
  32. #foo.sub!(/[\s\'\"\\\/\?\.\=\+\&\%]$/,'')
  33. #foo.gsub!(/[\s\'\"\\\/\?\.\=\+\&\%]/,'_')
  34. #foo.gsub!(/_+/,'_')
  35. foo
  36. end
  37. end

Niestety silnik forum brutalnie zamienił nieasciowe znaki na encje htmlowe. W dużym skrócie chodzi o wymienienie wszystkich możliwych literek, jakie maj± zostać wymienione na swoje asciiowe uproszczenia.

Offline

 

#22 2008-08-01 15:34:01

Paweł Kondzior
Cobra Commander
Od: Warszawa
Zarejestrowany: 2006-03-11
Posty: 458
Serwis

Re: Zamiana pojedynczych znaków

Wrzuc to na pastie.org jesli mozesz napewno sie przyda.


irb(main):001:0>

Offline

 

#23 2008-08-04 23:43:04

tczubinski
Adept
Zarejestrowany: 2006-04-17
Posty: 155

Re: Zamiana pojedynczych znaków

Może komu¶ się też przydać.

Kod:

require 'iconv'
require 'unicode'

class String 
  def to_ascii
    return if self.nil?
    self.chars.split('').collect { |c| (c[0] <= 127) ? c : translation_hash[c[0]] }.join
  end

  protected
    def translation_hash
      @translation_hash ||= setup_translation_hash      
    end
    
    def setup_translation_hash 
      accented_chars   = "ÀÁÂÃÄÅÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛŨÜÝâäàãáäåāă±ǎǟǡǻȁȃȧẵặçëêéèẽēĕėẻȅȇẹȩęḙḛềếễểḕḗệḝiìíîĩīĭïỉǐịįȉȋḭɨḯñòóôõōŏȯöỏőǒȍȏơǫọɵøồốỗổȱȫȭṍṏṑṓờớỡởợǭộǿùúûũūŭüủůűǔȕȗưụṳųṷṵṹṻǖǜǘǖǚừứữửựỳýŷỹȳẏÿỷẙƴỵˇĆĘŁŃӦݬ±ćęłń󶿼".chars.split('')
      unaccented_chars = "AAAAAACEEEEIIIIDNOOOOOxOUUUUUYaaaaaaaaaaaaaaaaaaaceeeeeeeeeeeeeeeeeeeeeeeeiiiiiiiiiiiiiiiiinoooooooooooooooooooooooooooooooooooouuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuyyyyyyyyyyyACELNOSZZacelnoszz".split('')
  
      translation_hash = {}
      accented_chars.each_with_index { |char, idx| translation_hash[char[0]] = unaccented_chars[idx] }
      translation_hash["Æ".chars[0]] = 'AE'
      translation_hash["æ".chars[0]] = 'ae'
      translation_hash["Œ".chars[0]] = 'OE'
      translation_hash["œ".chars[0]] = 'oe'
      translation_hash["ß".chars[0]] = 'ss'
      translation_hash
    end
end

Ostatnio edytowany przez tczubinski (2008-08-04 23:47:29)

Offline

 

#24 2009-04-10 12:28:46

teamon
Obserwator
Od: Bydgoszcz
Zarejestrowany: 2009-03-19
Posty: 56
Serwis

Re: Zamiana pojedynczych znaków

http://gist.github.com/93045 - simple yet powerful

Offline

 

#25 2009-04-10 17:15:54

drogus
RoR Guru
Od: Pruszków
Zarejestrowany: 2005-12-01
Posty: 1084
Serwis

Re: Zamiana pojedynczych znaków

tczubinski: ta wersja działa Ci z nowymi railsami?

Offline

 

Stopka forum

Powered by PunBB
© Copyright 2002–2005 Rickard Andersson