diff --git a/crates/bashkit/src/interpreter/mod.rs b/crates/bashkit/src/interpreter/mod.rs index b0b2a77d..08fe21e9 100644 --- a/crates/bashkit/src/interpreter/mod.rs +++ b/crates/bashkit/src/interpreter/mod.rs @@ -3147,14 +3147,29 @@ impl Interpreter { } } AssignmentValue::Array(words) => { - let mut expanded_values = Vec::new(); + // Expand each word, applying IFS word splitting for unquoted + // variable expansions: x="a b"; arr=($x) → arr=([0]="a" [1]="b") + // Quoted words (e.g., '' or "foo") are kept as single elements. + let mut all_fields = Vec::new(); for word in words.iter() { - let has_command_subst = word - .parts - .iter() - .any(|p| matches!(p, WordPart::CommandSubstitution(_))); - let value = self.expand_word(word).await?; - expanded_values.push((value, has_command_subst)); + let is_unquoted_expansion = !word.quoted + && word.parts.iter().any(|p| { + matches!( + p, + WordPart::Variable(_) + | WordPart::CommandSubstitution(_) + | WordPart::ArithmeticExpansion(_) + | WordPart::ParameterExpansion { .. } + | WordPart::ArrayAccess { .. } + ) + }); + if is_unquoted_expansion { + let fields = self.expand_word_to_fields(word).await?; + all_fields.extend(fields); + } else { + let value = self.expand_word(word).await?; + all_fields.push(value); + } } // Resolve nameref for array assignments @@ -3167,16 +3182,9 @@ impl Interpreter { 0 }; - for (value, has_command_subst) in expanded_values { - if has_command_subst && !value.is_empty() { - for part in value.split_whitespace() { - arr.insert(idx, part.to_string()); - idx += 1; - } - } else if !value.is_empty() || !has_command_subst { - arr.insert(idx, value); - idx += 1; - } + for field in all_fields { + arr.insert(idx, field); + idx += 1; } } } diff --git a/crates/bashkit/tests/spec_cases/bash/arrays.test.sh b/crates/bashkit/tests/spec_cases/bash/arrays.test.sh index 3a2b5cae..c601df9d 100644 --- a/crates/bashkit/tests/spec_cases/bash/arrays.test.sh +++ b/crates/bashkit/tests/spec_cases/bash/arrays.test.sh @@ -235,3 +235,21 @@ echo "${arr[1]}" 3 y ### end + +### unquoted_expansion_word_split_in_array +# arr=($x) should word-split on IFS +x="alpha beta gamma" +arr=($x) +echo "${#arr[@]}" +echo "${arr[1]}" +### expect +3 +beta +### end + +### unquoted_expansion_custom_ifs_in_array +# arr=($x) with custom IFS +IFS=","; x="a,b,c"; arr=($x); echo "${#arr[@]}" +### expect +3 +### end