diff --git a/crates/bashkit/src/interpreter/mod.rs b/crates/bashkit/src/interpreter/mod.rs index cf1140f6..2c683556 100644 --- a/crates/bashkit/src/interpreter/mod.rs +++ b/crates/bashkit/src/interpreter/mod.rs @@ -7752,9 +7752,13 @@ impl Interpreter { result } - /// Expand a variable by name, checking local scope, positional params, shell vars, then env /// Expand a string as a variable reference, or return as literal. /// Used for associative array keys which may be variable refs or literals. + /// + /// In real bash, associative array subscripts are treated as literal strings + /// unless they contain explicit `$var` or `${var}` references. A bare name + /// like `key` in `${assoc[key]}` is the string "key", NOT the value of + /// variable `$key`. (Issue #861) fn expand_variable_or_literal(&self, s: &str) -> String { // Handle $var and ${var} references in assoc array keys let trimmed = s.trim(); @@ -7762,9 +7766,7 @@ impl Interpreter { let var_name = var_name.trim_start_matches('{').trim_end_matches('}'); return self.expand_variable(var_name); } - if let Some(val) = self.variables.get(s) { - return val.clone(); - } + // Bare names are literal string keys — do NOT look up as variables. s.to_string() } diff --git a/crates/bashkit/tests/spec_cases/bash/assoc-arrays.test.sh b/crates/bashkit/tests/spec_cases/bash/assoc-arrays.test.sh index 7f18c9f1..fc0829a9 100644 --- a/crates/bashkit/tests/spec_cases/bash/assoc-arrays.test.sh +++ b/crates/bashkit/tests/spec_cases/bash/assoc-arrays.test.sh @@ -132,6 +132,47 @@ echo "${m[key]}" hello world ### end +### assoc_literal_key_not_variable +# Issue #861: subscripts should be literal strings, not variable lookups +x="outside" +declare -A map=([x]=found [outside]=wrong) +echo "${map[x]}" +### expect +found +### end + +### assoc_literal_key_numeric_variable +i=999 +declare -A assoc=([i]=correct [999]=incorrect) +echo "${assoc[i]}" +### expect +correct +### end + +### assoc_assignment_literal_key +x="other" +declare -A m6 +m6[x]="at-x" +m6[other]="at-other" +echo "${m6[x]} ${m6[other]}" +### expect +at-x at-other +### end + +### assoc_loop_key_variable_does_not_interfere +a="wrong_a" +b="wrong_b" +c="wrong_c" +declare -A data=([a]=1 [b]=2 [c]=3) +for k in "${!data[@]}"; do + echo "${k}=${data[$k]}" +done | sort +### expect +a=1 +b=2 +c=3 +### end + ### assoc_iteration declare -A m m[a]="1"