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_aArray, ENV.inspectString 등에서 나타나요.

예제에 관해

ENV의 일부 메서드는 ENV 그 자체를 돌려줘요. 보통 환경 변수가 많으니, 예제에서는 대부분 ENV.replaceENV.clearENV 내용을 초기화하고 시작해요.

주요 메서드 한눈에 보기

쿼리(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

이름 붙은 환경 변수를 만들거나 갱신하거나 삭제하고 값을 돌려줘요. namevalue 모두 String이거나 #to_str로 변환 가능해야 해요.

이름이 없을 때는:

  • valuenil이면 아무것도 안 해요.
  • valuenil이 아니면 그 이름/값으로 환경 변수를 만들어요.

이름이 이미 있을 때는:

  • valuenil이 아니면 값을 value로 갱신해요.
  • valuenil이면 환경 변수를 삭제해요.
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

블록이 falsenil을 돌려주는 항목을 삭제해요. 삭제가 있었으면 ENV, 없었으면 nil을 돌려줘요.

freeze # raises TypeError

TypeError를 던져요. ENV는 동결할 수 없어요.

include?, has_key?, member?, key?(name) → true or false

그 이름의 환경 변수가 있으면 true.

value?, has_value?(value) → true or false

어떤 환경 변수의 값이 valuetrue.

inspect → a_string

환경의 내용을 String으로 돌려줘요.

invert → hash of value/name pairs

키가 ENV 값, 값이 그에 대응하는 ENV 이름인 Hash를 돌려줘요. 중복 값이 있으면 덮어써요.

keep_if { |name, value| block } → ENV

블록이 falsenil을 돌려주는 환경 변수를 삭제하고 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를 쓰는 습관을 들이면 좋아요.