String 클래스
String 클래스
String은 Ruby에서 텍스트를 다루는 가장 기본적인 클래스예요. 문자, 단어, 문장, 문서까지 — 문자열 하나로 표현할 수 있는 건 모두 String 객체라고 보면 돼요.
출처: Ruby 4.0 API
본문
String이 담고 있는 콘텐츠는 따옴표('...' 또는 "...")나 퍼센트 리터럴(%q{...}, %Q{...} 등)로 만들 수 있어요. 또 필요에 따라 Encoding을 지정해서 인코딩(예: UTF-8)을 관리하죠.
이 문서는 String의 "무엇이 여기 있나"부터 시작해서 메서드를 알파벳 순으로 설명해요. 각 개념 섹션에 대한 자세한 설명은 아래 메서드별 문서에서 다뤄요.
무엇이 여기 있나 (What's Here)
String은 아래 카테고리로 정리할 수 있는 메서드들을 제공해요.
문자열 만들기 (Creating a New String)
- 문자열 분해:
String#bytes,String#chars,String#codepoints,String#grapheme_clusters,String#lines - 부분 문자열:
String#[],String#byteslice,String#chr,String#slice - 새 문자열 만들기:
String#center,String#concat,String#<<,String#dump,String#*,String#+,String#+@,String#-@
동결 (Frozen Strings)
String#-@는self가 이미 frozen이면self를, 아니면 임시 캐시에 있는 경우 그 frozen 문자열을 반환하거나 duplicate한 frozen 문자열을 만들어요.String#+@는 un-frozen한 문자열(복사본)을 반환해요.
조회 (Querying)
- 바이트/문자:
String#bytesize,String#length,String#size,String#sum - 부분 문자열 판별:
String#include?,String#index,String#rindex - 접두사/접미사:
String#start_with?,String#end_with? - 인코딩:
String#ascii_only?,String#encoding,String#valid_encoding?,String#unicode_normalized? - 기타:
String#match?,String#casecmp,String#casecmp?,String#empty?,String#eql?,String#hash,String#match
비교 (Comparing)
String#==,String#<=>,String#casecmp,String#casecmp?,String#eql?,String#hash
수정 (Modifying)
- 대체:
String#sub,String#sub!,String#gsub,String#gsub!,String#tr,String#tr!,String#tr_s,String#tr_s! - 삽입/삭제:
String#insert,String#delete,String#delete!,String#clear - 제거:
String#bytesplice,String#squeeze,String#squeeze!,String#strip,String#strip!,String#lstrip,String#lstrip!,String#rstrip,String#rstrip! - 치환:
String#replace,String#reverse,String#reverse! - 케이스:
String#upcase,String#upcase!,String#downcase,String#downcase!,String#capitalize,String#capitalize!,String#swapcase,String#swapcase! - 셀프 수정:
String#<<,String#concat,String#prepend,String#setbyte - 기타:
String#succ!,String#next!
변환 (Converting)
- 새 문자열로:
String#to_s,String#%,String#*,String#+,String#+@,String#-@,String#dump - 비문자열로:
String#to_i,String#to_f,String#to_r,String#to_c,String#to_sym - 기타:
String#encode,String#scrub
반복 (Iterating)
String#each_byte,String#each_char,String#each_codepoint,String#each_grapheme_cluster,String#each_line,String#upto
메서드
%(format, *objects) → string
self를 최대 하나의 % 지정자(%s, %d 등)로 해석해서 포매팅된 문자열을 반환해요. %d, %f, %s 등 printf 스타일 형식 지정자를 그대로 사용할 수 있어요:
'%5d' % 123 # => " 123"
'%.2f' % 3.14159 # => "3.14"
'%s %s' % ['a', 'b'] # => "a b"
*times → new_string
self를 times번 이어붙인 새 문자열을 반환해요:
'Hello! ' * 3 # => "Hello! Hello! Hello! "
times는 0 이상의 정수여야 해요. times가 0이면 빈 문자열을, 음수면 ArgumentError를 던져요.
times에 문자열을 전달하려 하면 TypeError가 발생해요. 이는 문자열 곱셈에 대한 명확한 의미 정의가 없기 때문이에요.
+other_string → new_string
self와 other_string을 이어붙인 새 문자열을 반환해요:
'Hello ' + 'World!' # => "Hello World!"
+@ → new_string
self가 frozen이면 단조된(duplicate된), un-frozen 문자열을 반환하고, 아니면 self를 그대로 반환해요.
-@ → new_string
self가 frozen이면 self를 반환하고, 아니면 (임시 캐시에 있는 경우) 그 frozen 문자열 또는 duplicate된 frozen 문자열을 반환해요.
<<object → self
object가 Integer면 이를 코드 포인트(문자)로 변환해서 self 끝에 추가하고, 그 외의 경우엔 문자열로 변환해서 이어붙여요. self를 반환하므로 체이닝이 가능하죠:
s = 'foo'
s << 'bar' # => "foobar"
s << 33 # => "foobar!"
→ new_string or nil
부분 문자열 접근의 왕이에요. 정수 인덱스, 정수 범위(방울), 시작+길이, 부분 문자열, 정규표현식(캡처 포함)까지 다양한 방식으로 문자열의 일부를 꺼냅니다.
[]=(index, ...) → object
self의 부분을 대체해요. []의 모든 형태(인덱스, 범위, 부분 문자열, 정규표현식)와 쌍을 이뤄요.
ascii_only? → true or false
self가 ASCII 문자열이면 true를, 아니면 false를 반환해요:
'abc'.ascii_only? # => true
'abc\u{6666}'.ascii_only? # => false
b → string
self를 복제해서 ASCII-8BIT 인코딩으로 만든 새 문자열을 반환해요.
bytes → array_of_integers
self의 각 바이트를 정수 배열로 반환해요:
'hello'.bytes # => [104, 101, 108, 108, 111]
byteslice(index, ...) → new_string or nil
바이트 단위로 부분 문자열을 반환해요. []와 비슷하지만 인덱스를 바이트 기준으로 다뤄요.
bytesize → integer
문자열의 바이트 수를 반환해요. String#length가 문자(코드 포인트) 수를 센다면, bytesize는 원시 바이트 수를 세죠:
'foo'.bytesize # => 3
'fooé'.bytesize # => 5
bytesplice(*args) → self
self의 일부를 대체하되, 인덱스를 바이트 단위로 다뤄요. 정수 위치 + 다른 문자열, 또는 범위, 또는 부분 문자열 + 길이 형태로 호출할 수 있어요.
capitalize(mapping = :ascii) → new_string
첫 글자는 대문자로, 나머지는 소문자로 만든 새 문자열을 반환해요:
'hello'.capitalize # => "Hello"
'HELLO'.capitalize # => "Hello"
'123abc'.capitalize # => "123abc"
케이스 매핑은 :ascii, :fold, :turkic 옵션의 영향을 받아요.
capitalize!(mapping) → self or nil
capitalize와 같되 self를 직접 수정해요. 변경이 있으면 self, 없으면 nil을 반환해요.
casecmp(other_string) → -1, 0, 1, or nil
대소문자를 무시하고 비교해요. 두 문자열이 같은 문자라도 케이스만 다르면 같다고 봐요:
'abc'.casecmp('ABC') # => 0
'abcdef'.casecmp('ABC') # => 1 # 'd' > 'C' 비교
둘 중 하나라도 ASCII가 아니라면 케이스-폴딩 없이 비교돼요.
casecmp?(other_string) → true, false, or nil
casecmp와 같지만 불리언을 반환해요:
'abc'.casecmp?('ABC') # => true
'abc'.casecmp?('xyz') # => false
center(width, pad_string = ' ') → new_string
왼쪽과 오른쪽에 pad_string을 넣어 self를 width만큼 가운데 정렬한 새 문자열을 반환해요:
'abc'.center(7) # => " abc "
'abc'.center(7, '-') # => "--abc--"
'abc'.center(2) # => "abc" # width가 더 짧으면 그대로
chars → array_of_strings
self를 문자(코드 포인트) 배열로 반환해요:
'hello'.chars # => ["h", "e", "l", "l", "o"]
chomp(line_sep = $/) → new_string
문자열 끝에서 레코드 구분자(기본 $/, "\n")를 제거한 복사본을 반환해요:
'hello'.chomp # => "hello"
'hello\n'.chomp # => "hello"
'hello\r\n'.chomp # => "hello"
'hello\n\n'.chomp # => "hello\n"
'hello'.chomp('llo') # => "he"
chr → string
self의 첫 문자를 담은 새 문자열을 반환해요:
'glark'.chr # => "g"
clear → self
self를 빈 문자열로 만들어요:
s = 'foo'
s.clear # => ""
codepoints → array_of_integers
self의 각 문자의 코드 포인트를 정수 배열로 반환해요:
'hello'.codepoints # => [104, 101, 108, 108, 111]
concat(*objects) → self
각 object를 self 끝에 이어붙여요. <<와 같은 기능이에요.
count(*selectors) → integer
selectors(문자 선택자)에 해당하는 문자들의 총 개수를 반환해요:
'hello'.count('l') # => 2
'hello'.count('lo') # => 3
'hello'.count('a-e') # => 1 # 'e'만 해당
'hello'.count('^l') # => 3 # 부정
'hello'.count('h', 'l') # => 3 # 다중 셀렉터는 합집합
crypt(*args) → string (⚠️ 2.6에서 deprecated)
delete(*selectors) → new_string
셀렉터에 해당하는 문자를 제거한 복사본을 반환해요:
'hello'.delete('l') # => "heo"
'hello'.delete('lo') # => "he"
'hello'.delete('a-e') # => "hllo"
'hello'.delete('^l') # => "ll"
'hello'.delete('h', 'l') # => "eo"
delete!(*selectors) → self or nil
delete와 같되 self를 직접 수정해요.
delete_prefix(prefix) → new_string
self가 prefix로 시작하면 그 부분을 제거한 복사본을 반환해요:
'hello'.delete_prefix('hel') # => "lo"
'hello'.delete_prefix('lo') # => "hello" # 안 맞으면 그대로
delete_suffix(suffix) → new_string
self가 suffix로 끝나면 그 부분을 제거한 복사본을 반환해요:
'hello'.delete_suffix('llo') # => "he"
downcase(mapping = :ascii) → new_string
소문자로 만든 복사본을 반환해요:
'hello'.downcase # => "hello"
'HELLO'.downcase # => "hello"
dump → new_string
self에서 따옴표를 벗기고 비인쇄 문자를 이스케이프한, 복사 가능한 리터럴 형태의 문자열을 반환해요. String#undump의 역연산이에요:
'hello'.dump # => "\"hello\""
each_byte {|byte| ... } → self
각 바이트를 정수로 블록에 넘겨요. 블록 없이 호출하면 Enumerator를 반환해요.
each_char {|char| ... } → self
각 문자를 블록에 넘겨요:
'hello'.each_char {|c| print c, ' ' } # => h e l l o
each_codepoint {|int| ... } → self
각 코드 포인트를 정수로 블록에 넘겨요.
each_grapheme_cluster {|clstr| ... } → self
각 그래핌 클러스터(사용자가 문자로 인식하는 단위, 예: 조합 자모)를 블록에 넘겨요.
each_line(line_sep = $/, chomp: false) {|substring| ... } → self
각 줄을 블록에 넘겨요. chomp: true를 주면 각 줄의 끝 줄바꿈을 제거해요:
"foo\nbar\n".each_line {|line| p line }
# "foo\n"
# "bar\n"
empty? → true or false
self가 비어 있으면 true:
'glark'.empty? # => false
''.empty? # => true
encode(*encodings, **options) → string
self를 지정한 인코딩으로 변환한 새 문자열을 반환해요.
encode!(*encodings, **options) → self
encode와 같되 self를 직접 변환해요.
encoding → encoding
self의 Encoding 객체를 반환해요.
end_with?(*patterns) → true or false
self가 주어진 패턴 중 하나로 끝나면 true:
'hello'.end_with?('llo') # => true
'hello'.end_with?('O') # => false (대소문자 구분)
eql?(object) → true or false
문자열과 인코딩이 모두 같으면 true. 객체 비교에 사용돼요 (==보다 엄격).
force_encoding(encoding) → self
인코딩을 바꿔도 바이트는 그대로 유지한 채 메타데이터만 바꿔요:
s = 'glark'
s.force_encoding(Encoding::ASCII_8BIT) # => "glark"
freeze → self
문자열을 동결(freeze)해요.
getbyte(index) → integer or nil
gsub(pattern, replacement) → new_string
pattern과 일치하는 모든 부분을 replacement로 바꾼 복사본을 반환해요. replacement로 문자열 또는 해시가 올 수 있고, 블록을 주면 각 일치부에 대해 블록을 호출해요:
'Hello'.gsub(/[aeiou]/, '*') # => "H*ll*"
gsub!(pattern, replacement) → self or nil
gsub와 같되 self를 직접 수정해요.
hash → integer
문자열의 해시 값을 반환해요.
hex → integer
수정자 접두어(0x 등)까지 해석해서 십육진수로 해석해요:
'0x0a'.hex # => 10
'-1234'.hex # => -4660
include?(other_string) → true or false
other_string이 부분 문자열로 포함되어 있으면 true:
'hello'.include?('lo') # => true
'hello'.include?('ol') # => false
index(substring, offset = 0) → integer or nil
initialize_copy(other_string) → self
insert(index, other_string) → self
intern → symbol (== to_sym)
length → integer (== size, 문자 수)
lines(separator = $/, chomp: false) → array_of_strings
lstrip → new_string
match?(pattern, offset = 0) → true or false
next → new_string (== succ)
oct → integer
ord → integer
partition(sep) → [head, sep, tail]
prepend(*other_strings) → self
replace(other_string) → self
reverse → new_string
rindex(*args) → integer or nil
rpartition(sep) → [head, sep, tail]
rstrip → new_string
scan(pattern) → array or self
scrub(*args) → new_string
setbyte(index, integer) → integer
shellescape → string
shellsplit → array
slice(...) → new_string or nil (== [])
split(field_sep, limit = 0) → array_of_substrings
squeeze(*selectors) → new_string
start_with?(*patterns) → true or false
strip(*selectors) → new_string
sub(pattern, replacement) → new_string
succ → new_string
sum(n = 16) → integer
swapcase(mapping = :ascii) → new_string
to_c → complex
to_f → float
to_i(base = 10) → integer
to_json_raw(*args)
to_json_raw_object()
to_r → rational
to_s → self or new_string
tr(selector, replacements) → new_string
tr_s(selector, replacements) → new_string
undump → new_string
unicode_normalize(form = :nfc) → string
unicode_normalize!(form = :nfc) → self
unicode_normalized?(form = :nfc) → true or false
unpack(template, offset: 0) {|o| ... } → object
unpack1(template, offset: 0) → object
upcase(mapping = :ascii) → new_string
upto(other_string, exclusive = false) {|string| ... } → self
valid_encoding? → true or false
주요 메서드 자세히
String은 위 목록처럼 매우 많은 메서드를 갖고 있어요. 특히 실무에서 자주 쓰는 것들을 골라 조금 더 자세히 볼게요.
split
구분자 기준으로 문자열을 잘라 배열로 돌려줘요. 구분자는 문자열, 정규표현식, 또는 기본 $/일 수 있어요:
'abracadabra'.split('a') # => ["", "br", "c", "d", "br"]
'foo bar baz'.split(' ') # => ["foo", "bar", "baz"]
'1, 2, 3'.split(', ') # => ["1", "2", "3"]
'1 + 1 == 2'.split(/\W+/) # => ["1", "1", "2"]
limit 인자로 반환 배열 크기를 제한하거나, 빈 문자열 포함 여부를 조절할 수 있어요:
'abracadabra'.split('', 3) # => ["a", "b", "racadabra"]
'abracadabra'.split('a', -1) # => ["", "br", "c", "d", "br", ""]
sub / gsub
pattern과 일치하는 첫 부분만(sub) 또는 전부(gsub)를 replacement로 치환해요. replacement가 문자열이면 그대로, 해시면 일치한 키를 값으로 치환하고, 블록이면 블록 반환 값으로 치환돼요:
s = 'abracadabra'
s.sub('bra', 'xyzzy') # => "axyzzycadabra"
s.gsub('bra', 'xyzzy') # => "axyzzycadaxyzzy"
s.gsub(/[aeiou]/, '*') # => "*br*c*d*br*"
문자 선택자 (Character Selectors)
count, delete, squeeze, strip, tr 등은 "문자 선택자"를 받아요. 선택자는:
- 단일 문자:
'o' - 여러 문자:
'aeiou' - 범위:
'a-z' - 부정:
'^aeiou' - 이스케이프:
'\\^','\\-','\\\\'
'Mississippi'.squeeze('s') # => "Misisippi"
'Mississippi'.squeeze('sp') # => "Misisipi"
'Mississippi'.squeeze('a-p') # => "Mississipi"
to_i / to_f / to_r / to_c
문자열 앞부분을 숫자로 해석하는 변환 메서드들이에요:
'123456'.to_i # => 123456
'3.14159'.to_f # => 3.14159
'123'.to_r # => (123/1)
'2+3i'.to_c.rect # => [2, 3]
String은 Ruby에서 가장 많이 쓰이는 클래스라서, 이렇게 카테고리별로 정리해 두면 필요한 메서드를 빠르게 찾을 수 있어요.