# recursive-env Look up env variables that are built from other env vars ## Why Shell env vars should evaluate recursively ```bash $ TEST1="test1" $ TEST2="${TEST1} test2" $ echo $test test1 test2 ``` But sometimes tooling sets env vars without evaluating them first. Take this simple program: ```rust fn main() { env::set_var("TEST1", "test1"); env::set_var("TEST2", "${TEST1} test2"); for (key, value) in env::vars() { println!("{key}: {value}"); } } // TODO: rewrite examples here with asserts. Run theses as part of tests ``` This will set 'TEST2' to the literal string "${TEST1} test2" instead of evaluating to "test1 test2". ```bash $ cargo run Finished dev [unoptimized + debuginfo] target(s) in 0.02s Running `target/debug/test` TEST1: test1 TEST2: ${TEST1} test2 ``` The solution is to get env vars through `recursive_env::var()` instead of `std::env::var()` ```rust use recursive_env::lookup; fn main() { env::set_var("TEST1", "test1"); env::set_var("TEST2", "${TEST1} test 2"); for (key, _) in env::vars() { let fixed = lookup(key) println!("{key}: {fixed}"); } } ``` ```bash $ cargo run Finished dev [unoptimized + debuginfo] target(s) in 0.02s Running `target/debug/test` TEST1: test1 TEST2: test1 test2 ``` ## Caveats - Sub expressions are not evaluated ```rust use recursive_env::lookup; fn main() { let key = "KEY"; let value = String::from("$(subexpression)"); env::set_var(&key, &value); assert_eq!(lookup::var(key).unwrap(), value); } ```