Stringi w Rubim

Posted by Jacek Galanciak on

String jest jedną z większych klas standardowych w języku Ruby - a to za sprawą ponad 70 metod. Nie trzeba chyba nikomu przypominać o ważności tego typu - przejdźmy od razu do poznawania, jak to wszystko wygląda w Rubim.

Tworzymy Stringa

Zacznijmy od pojedynczych apostrofów:

a = 'zwykle przypisanie' # => "zwykle przypisanie"
b = '"cos", \'cokolwiek\'' # => "\"cos\", 'cokolwiek'"
c = '(nie)dzialanie \n, /' # => "(nie)dzialanie \\n, /"

puts a, b, c

Na wyjściu mamy:

zwykle przypisanie
"cos", 'cokolwiek'
(nie)dzialanie \n, /

Widzimy tutaj, że jedyny znak, który może nam przerwać łańcuch to ', dlatego jeśli chcemy go umieścić w Stringu, musimy go poprzedzić ukośnikiem \. Zwrócmy uwagę na to, jak kodowane są znaki " i \.

Jeśli nie odpowiadają nam apostrofy, możemy użyć innych ograniczników:

a = %q/zwykle przypisanie/ # => "zwykle przypisanie"
b = %q!niemal\! ko\mpletna" ' / samowolka\\! # => "niemal! ko\\mpletna\" ' / samowolka\\"
c = %q(w nawiasach () tez dziala'") # => "w nawiasach () tez dziala'\""

puts a, b, c

Wyjście:

zwykle przypisanie
niemal! ko\mpletna" ' / samowolka\
w nawiasach () tez dziala'"

Powyższe przykłady pokazują, że możemy użyć alternatywnych apostrofów ograniczających naszego Stringa. Pamiętać trzeba tylko o tym, że jeśli umieszczamy ów apostrof w Stringu, należy poprzedzić go ukośnikiem, by zaznaczyć, że jeszcze go nie kończymy.

Podobnie jak w innych językach skryptowych, Stringi można tworzyć, uwzględniając dodatkowe podstawienia, za pomocą cudzysłowia:

a = "zwykle podstawienie" # => "zwykle podstawienie"
b = "dodatkowe ' znaki \\ / \"" # => "dodatkowe ' znaki \\ / \""
c = "2 + 2 = #{2 + 2}\na: #{a.upcase}" # => "2 + 2 = 4\na: ZWYKLE PODSTAWIENIE"
d = "5! = #{ def factorial(n)
               n > 1 ? n*factorial(n - 1) : 1
             end
             factorial(5)}" # => "5! = 120"

puts a, b, c, d

Na wyjściu otrzymujemy:

zwykle podstawienie
dodatkowe ' znaki \ / "
2 + 2 = 4
a: ZWYKLE PODSTAWIENIE
5! = 120

Powyższe przykłady pokazują, że znaki cudzysłowia oferują nam znacznie więcej niż apostrofy: możemy dodatkowo podstawiać znaki specjalne (takie jak koniec linii), wartości zmiennych czy nawet duże i skomplikowane wyrażenia.

Istnieje możliwość podawania kodów ASCII wybranych przez nas znaków:

puts "\141b\143"

Na wyjściu otrzymamy oczywiście abc. Kody podajemy w postaci ósemkowej!

Podobnie jak apostrofy, znaki cudzysłowia można zastępować alternatywną formą:

a = %Q{To jest to samo, co "} # => "To jest to samo, co \""
b = %<tak tez mozna: #{1 + 1}> # => "tak tez mozna: 2"
c = %{dzialaja znaki "/' i {}, ale samo \} i \\ juz nie}
# => "dzialaja znaki \"/' i {}, ale samo } i \\ juz nie"
puts a, b, c

Wyjście:

To jest to samo, co "
tak tez mozna: 2
dzialaja znaki "/' i {}, ale samo } i \ juz nie

Kiedy trzeba dłuższych łańcuchów…

Czasem musimy użyć nieco dłuższych Stringów, a formatowanie takich nie jest zbyt wygodne przy użyciu wymienionych wyżej sposobów. Z pomocą przychodzi nam znana z innych języków skryptowych konstrukcja tzn. heredoc.

a = <<HERE
To jest przykladowy
heredoc z podstawieniem: #{1 + 1}
Dzialaja znaki " ' /, ale nie \\
HERE

b = <<-'TUTAJ'
To jest przykladowy
heredoc z podstawieniem: #{1 + 1}
Dzialaja znaki " ' /, ale nie \\
TUTAJ

puts a, b

Wyjście:

To jest przykladowy
heredoc z podstawieniem: 2
Dzialaja znaki " ' /, ale nie \
To jest przykladowy
heredoc z podstawieniem: #{1 + 1}
Dzialaja znaki " ' /, ale nie \\

Łatwo zauważyć różnice w poszczególnych formach oraz fakt, że jeden z nich jest cudzysłowiem, a drugi - apostrofem.

Stringowa “matematyka”

W Rubim Stringi możemy nie tylko sklejać, ale i mnożyć:

puts "bua" + "ha"*3

buahahaha

To nie wszystko. Mamy także operator modulo ( % ), który w Stringach jest operatorem formatowania:

puts "%.5f" % Math::PI
puts "%s ma %02d lat" % ["Ala", 5]

Co na wyjściu da nam:

3.14159
Ala ma 05 lat

Sposób formatowania jest taki sam, jak w metodzie sprintf, przy więcej niż jednym elemencie należy użyć tablicy do przekazywania parametrów.

Szczypta metod

Poznamy teraz parę wybranych metod (umówienie całości nie ma sensu - ri String!).

"Ala ma tyfus".length # => 12
"przykladowy tekst".capitalize # => "Przykladowy tekst"
"".empty? # => true
"abc".empty? # => false
"ucinam".chop # => "ucina"
"gdzie ten kot sie schowal?".index("kot")
                                    # => 10
"ruby".reverse # "ybur"
"Ala ma kota"[0] # 65
"Ala ma kota"[0..2] # "Ala"
"Ala ma kota"[-4..-1] # "kota"
"Ala ma kota".slice(-4..-1) # "kota"
                                    # metody te są synonimiczne
"ssssssciiiiisssssskammmy".squeeze("sm")
                                    # => "sciiiiiskamy"
"12:15:30".split(':') # => ["12", "15", "30"]
"abcd".succ # => "abce"
"99zz".succ # => "100aa"
"PoSzLeM nA iMpReSke".swapcase # => "pOsZlEm Na ImPrEsKE"
"125".to_i # => 125
"abc" > "cde" # false
"abc" <=> "cde" # -1

“Psujemy” Stringa

Kiedy wywołujemy wszystkie powyższe metody, wartość samego obiektu nie jest modyfikowana - zwracana jest jedynie wartość z wynikiem działania. Istnieje jednak możliwość bezpośredniej zmiany wartości naszego Stringa:

a = "psuja!" # => "psuja!"
a.upcase # => "PSUJA!"
a # => "psuja!"
a.upcase! # => "PSUJA!"
a # => "PSUJA!"

Przyjęło się w Rubim, że metody zakończone wykrzyknikiem mogą być niebezpieczne dla naszych danych. W kontekście Stringów bezpowrotnie modyfikują sam obiekt.

Podsumowanie

Stringi w Rubim mają potężne możliwości. Warto je wszystkie poznać, choćby po to, by uniknąć ponownego pisania gotowego już kodu.