ENV 클래스
ENV 클래스
ENV는 환경 변수(environment variables)에 접근하는 해시(hash)처럼 동작하는 객체예요.
운영체제와의 상호작용
ENV 객체는 운영체제의 환경 변수와 직접 소통해요:
ENV에서 어떤 이름의 값을 읽으면, 현재 환경 변수 중에서 그 값을 가져와요.ENV에 이름-값 쌍을 만들거나 설정하면, 즉시 환경 변수에 반영돼요.ENV에서 이름-값 쌍을 삭제하면, 즉시 환경 변수에서 삭제돼요.
이름과 값
일반적으로 이름이나 값은 String이에요.
유효한 이름과 값
각 이름이나 값은 다음 중 하나여야 해요:
String#to_str에 응답해서String을 돌려주는 객체 (그String이 이름이나 값으로 사용돼요)
유효하지 않은 이름과 값
새 이름은:
- 빈 문자열일 수 없어요:
ENV[''] = '0'
# Raises Errno::EINVAL (Invalid argument - ruby_setenv())
"="문자를 포함할 수 없어요:
ENV['='] = '0'
# Raises Errno::EINVAL (Invalid argument - ruby_setenv(=))
새 이름이나 값은:
#to_str에 응답하지 않는String이 아닌 객체일 수 없어요:
ENV['foo'] = Object.new
# Raises TypeError (no implicit conversion of Object into String)
ENV[Object.new] = '0'
# Raises TypeError (no implicit conversion of Object into String)
- NUL 문자
"\0"를 포함할 수 없어요:
ENV['foo'] = "\0"
# Raises ArgumentError (bad environment variable value: contains null byte)
ENV["\0"] == '0'
# Raises ArgumentError (bad environment variable name: contains null byte)
- ASCII 호환되지 않는 인코딩(UTF-16LE나 ISO-2022-JP 같은)을 가질 수 없어요:
ENV['foo'] = '0'.force_encoding(Encoding::ISO_2022_JP)
# Raises ArgumentError (bad environment variable name: ASCII incompatible encoding: ISO-2022-JP)
순서에 관해
ENV는 운영체제의 환경 변수에서 발견되는 순서대로 이름/값 쌍을 나열해요. 그래서 ENV 내용의 순서는 OS에 의존적이고, 때로는 결정할 수 없어요. 이건 ENV 메서드가 돌려주는 Hash, Enumerator, ENV.keys·ENV.values·ENV.to_a의 Array, ENV.inspect의 String 등에서 나타나요.
예제에 관해
ENV의 일부 메서드는 ENV 그 자체를 돌려줘요. 보통 환경 변수가 많으니, 예제에서는 대부분 ENV.replace나 ENV.clear로 ENV 내용을 초기화하고 시작해요.
주요 메서드 한눈에 보기
쿼리(Querying): ::[], ::empty?, ::has_value?/::value?, ::include?/::has_key?/::key?/::member?, ::key, ::size/::length
할당(Assigning): ::[]=/::store, ::clear, ::update/::merge!, ::replace
삭제(Deleting): ::delete, ::delete_if, ::keep_if, ::reject!, ::select!/::filter!, ::shift
반복(Iterating): ::each/::each_pair, ::each_key, ::each_value
변환(Converting): ::assoc, ::clone, ::except, ::fetch, ::inspect, ::invert, ::keys, ::rassoc, ::reject, ::select/::filter, ::slice, ::to_a, ::to_h, ::to_hash, ::to_s, ::values, ::values_at
출처: Ruby 3.3 API
본문
ENV[name] → value
name에 해당하는 환경 변수의 값을 돌려줘요:
ENV['foo'] = '0'
ENV['foo'] # => "0"
그 이름의 변수가 없으면 nil을 돌려줘요. name이 유효하지 않으면 예외를 던져요.
ENV[name] = value, store(name, value) → value
이름 붙은 환경 변수를 만들거나 갱신하거나 삭제하고 값을 돌려줘요. name과 value 모두 String이거나 #to_str로 변환 가능해야 해요.
이름이 없을 때는:
value가nil이면 아무것도 안 해요.value가nil이 아니면 그 이름/값으로 환경 변수를 만들어요.
이름이 이미 있을 때는:
value가nil이 아니면 값을value로 갱신해요.value가nil이면 환경 변수를 삭제해요.
ENV['foo'] = '0' # => '0'
ENV.store('bar', '1') # => '1'
ENV['foo'] = nil # => nil
ENV.include?('foo') # => false
assoc(name) → [name, value] or nil
name에 해당하는 환경 변수의 이름과 값을 담은 2-요소 Array를 돌려줘요. 없으면 nil을 돌려줘요.
ENV.replace('foo' => '0', 'bar' => '1')
ENV.assoc('foo') # => ['foo', '0']
clear → ENV
모든 환경 변수를 제거하고 ENV를 돌려줘요:
ENV.replace('foo' => '0', 'bar' => '1')
ENV.size # => 2
ENV.clear # => ENV
ENV.size # => 0
clone(freeze: nil) # raises TypeError
TypeError를 던져요. ENV는 프로세스 전역 환경 변수의 래퍼라서 복제(clone)는 의미가 없기 때문이에요. ENV 데이터를 해시로 복사하려면 to_h를 쓰세요.
delete(name) → value
이름이 있는 환경 변수를 삭제하고 값을 돌려줘요. 블록이 없고 변수가 없으면 nil을, 블록이 있고 변수가 없으면 블록에 name을 넘겨 그 반환값을 돌려줘요:
ENV['foo'] = '0'
ENV.delete('foo') # => '0'
ENV.delete('foo') { |name| name * 2 } # => "foofoo"
delete_if { |name, value| block } → ENV, delete_if → an_enumerator
각 환경 변수의 이름과 값을 2-요소 Array로 넘기면서 블록이 참이면 삭제하고, ENV를 돌려줘요. 블록이 없으면 Enumerator를 돌려줘요.
ENV.replace('foo' => '0', 'bar' => '1', 'baz' => '2')
ENV.delete_if { |name, value| name.start_with?('b') } # => ENV
ENV # => {"foo"=>"0"}
dup # raises TypeError
TypeError를 던져요. ENV는 싱글턴 객체이기 때문이에요. 복사하려면 to_h를 쓰세요.
each, each_pair { |name, value| block } → ENV
각 환경 변수의 이름과 값을 2-요소 Array로 넘겨요. 블록이 없으면 Enumerator를 돌려줘요.
h = {}
ENV.each_pair { |name, value| h[name] = value } # => ENV
h # => {"bar"=>"1", "foo"=>"0"}
each_key { |name| block } → ENV
각 환경 변수의 이름을 넘겨요.
each_value { |value| block } → ENV
각 환경 변수의 값을 넘겨요.
empty? → true or false
환경 변수가 없으면 true, 있으면 false.
except(*keys) → a_hash
주어진 키들을 제외한 ENV와 그 값들을 해시로 돌려줘요:
ENV.except("TERM","HOME") #=> {"LANG"=>"en_US.UTF-8"}
fetch(name) → value, fetch(name, default) → value, fetch(name) { |name| block } → value
이름의 값이 있으면 돌려주고, 없으면 블록이나 기본값을 사용해요. 기본값이나 블록도 없으면 KeyError를 던져요.
ENV['foo'] = '0'
ENV.fetch('foo') # => '0'
ENV.fetch('foo') { |name| :need_not_return_a_string } # => :need_not_return_a_string
ENV.fetch('foo') # Raises KeyError (key not found: "foo")
select, filter { |name, value| block } → hash of name/value pairs
블록이 참인 이름/값 쌍만 담은 Hash를 돌려줘요.
ENV.select { |name, value| name.start_with?('b') } # => {"bar"=>"1", "baz"=>"2"}
select!, filter! { |name, value| block } → ENV or nil
블록이 false나 nil을 돌려주는 항목을 삭제해요. 삭제가 있었으면 ENV, 없었으면 nil을 돌려줘요.
freeze # raises TypeError
TypeError를 던져요. ENV는 동결할 수 없어요.
include?, has_key?, member?, key?(name) → true or false
그 이름의 환경 변수가 있으면 true.
value?, has_value?(value) → true or false
어떤 환경 변수의 값이 value면 true.
inspect → a_string
환경의 내용을 String으로 돌려줘요.
invert → hash of value/name pairs
키가 ENV 값, 값이 그에 대응하는 ENV 이름인 Hash를 돌려줘요. 중복 값이 있으면 덮어써요.
keep_if { |name, value| block } → ENV
블록이 false나 nil을 돌려주는 환경 변수를 삭제하고 ENV를 돌려줘요.
key(value) → name or nil
value를 가진 첫 번째 환경 변수의 이름을 돌려줘요. 없으면 nil.
keys → array of names
모든 변수 이름을 Array로 돌려줘요.
length, size → an_integer
환경 변수의 개수를 돌려줘요:
ENV.replace('foo' => '0', 'bar' => '1')
ENV.length # => 2
ENV.size # => 2
update, merge!(*hashes) → ENV, update(*hashes) { |name, env_val, hash_val| block } → ENV
주어진 hash의 각 키/값 쌍을 ENV에 추가하고 ENV를 돌려줘요. nil 값은 해당 항목을 삭제하고, 이미 있는 이름은 기본적으로 덮어써요. 블록이 있으면 이름·기존값·해시값을 넘겨 블록의 반환값을 새 값으로 써요:
ENV.merge!('baz' => '2', 'bat' => '3') # => {"bar"=>"1", "bat"=>"3", "baz"=>"2", "foo"=>"0"}
ENV.merge!('foo' => '5') { |name, env_val, hash_val | env_val + hash_val } # => {"bar"=>"1", "foo"=>"45"}
rassoc(value) → [name, value] or nil
value를 가진 첫 번째 환경 변수의 이름과 값을 담은 2-요소 Array를 돌려줘요.
rehash → nil
Hash와의 호환을 위해 제공돼요. ENV를 수정하지 않고 nil을 돌려줘요.
reject { |name, value| block } → hash of name/value pairs
블록이 참인 항목을 제외한 Hash를 돌려줘요.
reject! { |name, value| block } → ENV or nil
delete_if와 비슷하지만 변경이 없으면 nil을 돌려줘요.
replace(hash) → ENV
환경 변수의 전체 내용을 주어진 hash의 이름/값 쌍으로 교체하고 ENV를 돌려줘요:
ENV.replace('foo' => '0', 'bar' => '1') # => ENV
ENV.to_hash # => {"bar"=>"1", "foo"=>"0"}
shift → [name, value] or nil
첫 번째 환경 변수를 제거하고 그 이름과 값을 담은 2-요소 Array를 돌려줘요. 비어 있으면 nil.
slice(*names) → hash of name/value pairs
주어진 ENV 이름들과 그에 대응하는 값들의 Hash를 돌려줘요:
ENV.slice('foo', 'baz') # => {"foo"=>"0", "baz"=>"2"}
to_a → array of 2-element arrays
ENV의 내용을 이름/값 쌍의 2-요소 Array들의 Array로 돌려줘요:
ENV.to_a # => [["bar", "1"], ["foo", "0"]]
to_h → hash of name/value pairs, to_h {|name, value| block }
블록이 없으면 모든 이름/값 쌍을 담은 Hash를, 블록이 있으면 각 쌍을 블록에 넘겨 반환된 2-요소 Array로 만든 Hash를 돌려줘요:
ENV.to_hash # => {"bar"=>"1", "foo"=>"0"}
ENV.to_h { |name, value| [name.to_sym, value.to_i] } # => {:bar=>1, :foo=>0}
to_hash → hash of name/value pairs
ENV의 모든 이름/값 쌍을 담은 Hash를 돌려줘요.
to_s → "ENV"
String 'ENV'를 돌려줘요.
values → array of values
모든 환경 변수 값을 Array로 돌려줘요.
values_at(*names) → array of values
주어진 이름들과 연결된 환경 변수 값들을 담은 Array를 돌려줘요. 없는 이름은 nil로 채워요:
ENV.values_at('foo', 'bat', 'bar', 'bam') # => ["0", nil, "1", nil]
더 알아보기
ENV를 해시처럼 초기화하는ENV.replace는 실습에서 정말 자주 써요. 예제처럼 환경 변수를 깨끗하게 리셋하고 시작하면 결과가 예측 가능해져요.ENV자체는 싱글턴이라clone·dup·freeze가 전부TypeError를 던져요. 복사본이 필요하면ENV.to_h를 쓰는 습관을 들이면 좋아요.