From f8cb0d9f31871cb0bf74a937dd1fc5bdd17cd07d Mon Sep 17 00:00:00 2001 From: Ramesh Padmanabhaiah <22363102+codeforester@users.noreply.github.com> Date: Sun, 9 Aug 2026 11:42:25 -0700 Subject: [PATCH 1/2] publish bulk arrays with single evals --- lib/bash/arg/lib_arg.sh | 10 ++-------- lib/bash/list/lib_list.sh | 25 +++++++------------------ 2 files changed, 9 insertions(+), 26 deletions(-) diff --git a/lib/bash/arg/lib_arg.sh b/lib/bash/arg/lib_arg.sh index 4e8cf55..f2f83d8 100644 --- a/lib/bash/arg/lib_arg.sh +++ b/lib/bash/arg/lib_arg.sh @@ -256,10 +256,7 @@ base_arg_parse() { __base_bash_libs_arg_set_assoc_value__ "$__base_bash_libs_arg_options_name" "$__base_bash_libs_arg_option_name" "${__base_bash_libs_arg_options[$__base_bash_libs_arg_option_name]}" done fi - eval "$__base_bash_libs_arg_positionals_name=()" - for __base_bash_libs_arg_current in "${__base_bash_libs_arg_positionals[@]+"${__base_bash_libs_arg_positionals[@]}"}"; do - eval "$__base_bash_libs_arg_positionals_name+=(\"\$__base_bash_libs_arg_current\")" - done + eval "$__base_bash_libs_arg_positionals_name=(\"\${__base_bash_libs_arg_positionals[@]}\")" for __base_bash_libs_arg_repeatable_name in "${__base_bash_libs_arg_repeatable_names[@]+"${__base_bash_libs_arg_repeatable_names[@]}"}"; do __base_bash_libs_arg_publish_values=() @@ -274,10 +271,7 @@ base_arg_parse() { fi done fi - eval "$__base_bash_libs_arg_repeatable_name=()" - for __base_bash_libs_arg_repeatable_value in "${__base_bash_libs_arg_publish_values[@]+"${__base_bash_libs_arg_publish_values[@]}"}"; do - eval "$__base_bash_libs_arg_repeatable_name+=(\"\$__base_bash_libs_arg_repeatable_value\")" - done + eval "$__base_bash_libs_arg_repeatable_name=(\"\${__base_bash_libs_arg_publish_values[@]}\")" done return 0 } diff --git a/lib/bash/list/lib_list.sh b/lib/bash/list/lib_list.sh index f31a9a8..4b13c41 100644 --- a/lib/bash/list/lib_list.sh +++ b/lib/bash/list/lib_list.sh @@ -46,8 +46,8 @@ base_list_prepend() { return 2 fi __base_bash_libs_std_assert_public_variable_names__ base_list_prepend "${1-}" || return 1 - local __base_bash_libs_list_array_name="$1" __base_bash_libs_list_item - local -a __base_bash_libs_list_values=() __base_bash_libs_list_current=() + local __base_bash_libs_list_array_name="$1" + local -a __base_bash_libs_list_values=() __base_bash_libs_list_current=() __base_bash_libs_list_combined=() base_std_assert_variable_name "$__base_bash_libs_list_array_name" base_std_assert_indexed_array "$__base_bash_libs_list_array_name" @@ -55,13 +55,8 @@ base_list_prepend() { shift __base_bash_libs_list_values=("$@") eval "if [[ -n \"\${${__base_bash_libs_list_array_name}[@]+set}\" ]]; then __base_bash_libs_list_current=(\"\${${__base_bash_libs_list_array_name}[@]}\"); fi" - eval "$__base_bash_libs_list_array_name=()" - for __base_bash_libs_list_item in "${__base_bash_libs_list_values[@]+"${__base_bash_libs_list_values[@]}"}"; do - eval "$__base_bash_libs_list_array_name+=(\"\$__base_bash_libs_list_item\")" - done - for __base_bash_libs_list_item in "${__base_bash_libs_list_current[@]+"${__base_bash_libs_list_current[@]}"}"; do - eval "$__base_bash_libs_list_array_name+=(\"\$__base_bash_libs_list_item\")" - done + __base_bash_libs_list_combined=("${__base_bash_libs_list_values[@]+"${__base_bash_libs_list_values[@]}"}" "${__base_bash_libs_list_current[@]+"${__base_bash_libs_list_current[@]}"}") + eval "$__base_bash_libs_list_array_name=(\"\${__base_bash_libs_list_combined[@]}\")" } # @@ -70,7 +65,7 @@ base_list_prepend() { base_list_remove() { base_std_assert_arg_count "$#" 2 __base_bash_libs_std_assert_public_variable_names__ base_list_remove "${1-}" || return 1 - local __base_bash_libs_list_array_name="$1" __base_bash_libs_list_needle="$2" __base_bash_libs_list_item + local __base_bash_libs_list_array_name="$1" __base_bash_libs_list_needle="$2" local -a __base_bash_libs_list_current=() __base_bash_libs_list_filtered=() base_std_assert_variable_name "$__base_bash_libs_list_array_name" @@ -83,10 +78,7 @@ base_list_remove() { __base_bash_libs_list_filtered+=("$__base_bash_libs_list_item") done - eval "$__base_bash_libs_list_array_name=()" - for __base_bash_libs_list_item in "${__base_bash_libs_list_filtered[@]+"${__base_bash_libs_list_filtered[@]}"}"; do - eval "$__base_bash_libs_list_array_name+=(\"\$__base_bash_libs_list_item\")" - done + eval "$__base_bash_libs_list_array_name=(\"\${__base_bash_libs_list_filtered[@]}\")" } base_list_contains() { @@ -126,10 +118,7 @@ base_list_unique() { __base_bash_libs_list_unique+=("$__base_bash_libs_list_item") done - eval "$__base_bash_libs_list_result_name=()" - for __base_bash_libs_list_item in "${__base_bash_libs_list_unique[@]+"${__base_bash_libs_list_unique[@]}"}"; do - eval "$__base_bash_libs_list_result_name+=(\"\$__base_bash_libs_list_item\")" - done + eval "$__base_bash_libs_list_result_name=(\"\${__base_bash_libs_list_unique[@]}\")" } base_list_length() { From 6d8e0b222acf96d5e2f8cb7f9837e65e7d6d5c26 Mon Sep 17 00:00:00 2001 From: Ramesh Padmanabhaiah <22363102+codeforester@users.noreply.github.com> Date: Sun, 9 Aug 2026 11:47:31 -0700 Subject: [PATCH 2/2] preserve empty arrays during bulk publication --- lib/bash/arg/lib_arg.sh | 28 ++++++++++++++++++---------- lib/bash/list/lib_list.sh | 20 ++++++++++++++++---- 2 files changed, 34 insertions(+), 14 deletions(-) diff --git a/lib/bash/arg/lib_arg.sh b/lib/bash/arg/lib_arg.sh index f2f83d8..34f8591 100644 --- a/lib/bash/arg/lib_arg.sh +++ b/lib/bash/arg/lib_arg.sh @@ -6,7 +6,7 @@ [[ -n "${BASE_BASH_LIBS_ARG_LOADED:-}" ]] && return 0 if [[ "${BASE_BASH_LIBS_STDLIB_LOADED:-}" != "1" ]]; then printf '%s\n' "Error: lib_arg.sh requires lib_std.sh to be sourced first." >&2 - return 1 2>/dev/null || exit 1 + return 1 2> /dev/null || exit 1 fi readonly BASE_BASH_LIBS_ARG_LOADED=1 @@ -23,9 +23,9 @@ __base_bash_libs_arg_assert_distinct_names__() { local __base_bash_libs_arg_left_index __base_bash_libs_arg_right_index for ((__base_bash_libs_arg_left_index = 0; __base_bash_libs_arg_left_index < ${#__base_bash_libs_arg_distinct_names[@]}; __base_bash_libs_arg_left_index++)); do - for ((__base_bash_libs_arg_right_index = __base_bash_libs_arg_left_index + 1; - __base_bash_libs_arg_right_index < ${#__base_bash_libs_arg_distinct_names[@]}; - __base_bash_libs_arg_right_index++)); do + for ((__base_bash_libs_arg_right_index = __base_bash_libs_arg_left_index + 1; \ + __base_bash_libs_arg_right_index < ${#__base_bash_libs_arg_distinct_names[@]}; \ + __base_bash_libs_arg_right_index++)); do if [[ "${__base_bash_libs_arg_distinct_names[__base_bash_libs_arg_left_index]}" == "${__base_bash_libs_arg_distinct_names[__base_bash_libs_arg_right_index]}" ]]; then base_std_log_error -l base_bash_libs.arg \ "base_arg_parse: caller-owned variables must be distinct; '${__base_bash_libs_arg_distinct_names[__base_bash_libs_arg_left_index]}' was provided more than once." @@ -111,7 +111,7 @@ __base_bash_libs_arg_parse_specs__() { base_std_log_error -l base_bash_libs.arg "base_arg_parse: option spec '$__base_bash_libs_arg_spec' contains an empty option token." return 2 fi - IFS='|' read -r -a __base_bash_libs_arg_tokens <<<"$__base_bash_libs_arg_tokens_part" + IFS='|' read -r -a __base_bash_libs_arg_tokens <<< "$__base_bash_libs_arg_tokens_part" for __base_bash_libs_arg_token in "${__base_bash_libs_arg_tokens[@]+"${__base_bash_libs_arg_tokens[@]}"}"; do if ! [[ "$__base_bash_libs_arg_token" =~ $__base_bash_libs_arg_token_re ]] || [[ "$__base_bash_libs_arg_token" == *"="* ]]; then base_std_log_error -l base_bash_libs.arg "base_arg_parse: option spec '$__base_bash_libs_arg_spec' has invalid option token '$__base_bash_libs_arg_token'." @@ -256,22 +256,30 @@ base_arg_parse() { __base_bash_libs_arg_set_assoc_value__ "$__base_bash_libs_arg_options_name" "$__base_bash_libs_arg_option_name" "${__base_bash_libs_arg_options[$__base_bash_libs_arg_option_name]}" done fi - eval "$__base_bash_libs_arg_positionals_name=(\"\${__base_bash_libs_arg_positionals[@]}\")" + if ((${#__base_bash_libs_arg_positionals[@]} > 0)); then + eval "$__base_bash_libs_arg_positionals_name=(\"\${__base_bash_libs_arg_positionals[@]}\")" + else + eval "$__base_bash_libs_arg_positionals_name=()" + fi for __base_bash_libs_arg_repeatable_name in "${__base_bash_libs_arg_repeatable_names[@]+"${__base_bash_libs_arg_repeatable_names[@]}"}"; do __base_bash_libs_arg_publish_values=() # shellcheck disable=SC2199 # The + expansion safely detects Bash 4.2 empty arrays under nounset. if [[ -n "${__base_bash_libs_arg_repeatable_values[@]+set}" ]]; then - for ((__base_bash_libs_arg_repeatable_index = 0; - __base_bash_libs_arg_repeatable_index < ${#__base_bash_libs_arg_repeatable_values[@]}; - __base_bash_libs_arg_repeatable_index += 2)); do + for ((__base_bash_libs_arg_repeatable_index = 0; \ + __base_bash_libs_arg_repeatable_index < ${#__base_bash_libs_arg_repeatable_values[@]}; \ + __base_bash_libs_arg_repeatable_index += 2)); do if [[ "${__base_bash_libs_arg_repeatable_values[__base_bash_libs_arg_repeatable_index]}" == "$__base_bash_libs_arg_repeatable_name" ]]; then __base_bash_libs_arg_repeatable_value="${__base_bash_libs_arg_repeatable_values[__base_bash_libs_arg_repeatable_index + 1]}" __base_bash_libs_arg_publish_values+=("$__base_bash_libs_arg_repeatable_value") fi done fi - eval "$__base_bash_libs_arg_repeatable_name=(\"\${__base_bash_libs_arg_publish_values[@]}\")" + if ((${#__base_bash_libs_arg_publish_values[@]} > 0)); then + eval "$__base_bash_libs_arg_repeatable_name=(\"\${__base_bash_libs_arg_publish_values[@]}\")" + else + eval "$__base_bash_libs_arg_repeatable_name=()" + fi done return 0 } diff --git a/lib/bash/list/lib_list.sh b/lib/bash/list/lib_list.sh index 4b13c41..b45dc85 100644 --- a/lib/bash/list/lib_list.sh +++ b/lib/bash/list/lib_list.sh @@ -6,7 +6,7 @@ [[ -n "${BASE_BASH_LIBS_LIST_LOADED:-}" ]] && return 0 if [[ "${BASE_BASH_LIBS_STDLIB_LOADED:-}" != "1" ]]; then printf '%s\n' "Error: lib_list.sh requires lib_std.sh to be sourced first." >&2 - return 1 2>/dev/null || exit 1 + return 1 2> /dev/null || exit 1 fi readonly BASE_BASH_LIBS_LIST_LOADED=1 @@ -56,7 +56,11 @@ base_list_prepend() { __base_bash_libs_list_values=("$@") eval "if [[ -n \"\${${__base_bash_libs_list_array_name}[@]+set}\" ]]; then __base_bash_libs_list_current=(\"\${${__base_bash_libs_list_array_name}[@]}\"); fi" __base_bash_libs_list_combined=("${__base_bash_libs_list_values[@]+"${__base_bash_libs_list_values[@]}"}" "${__base_bash_libs_list_current[@]+"${__base_bash_libs_list_current[@]}"}") - eval "$__base_bash_libs_list_array_name=(\"\${__base_bash_libs_list_combined[@]}\")" + if ((${#__base_bash_libs_list_combined[@]} > 0)); then + eval "$__base_bash_libs_list_array_name=(\"\${__base_bash_libs_list_combined[@]}\")" + else + eval "$__base_bash_libs_list_array_name=()" + fi } # @@ -78,7 +82,11 @@ base_list_remove() { __base_bash_libs_list_filtered+=("$__base_bash_libs_list_item") done - eval "$__base_bash_libs_list_array_name=(\"\${__base_bash_libs_list_filtered[@]}\")" + if ((${#__base_bash_libs_list_filtered[@]} > 0)); then + eval "$__base_bash_libs_list_array_name=(\"\${__base_bash_libs_list_filtered[@]}\")" + else + eval "$__base_bash_libs_list_array_name=()" + fi } base_list_contains() { @@ -118,7 +126,11 @@ base_list_unique() { __base_bash_libs_list_unique+=("$__base_bash_libs_list_item") done - eval "$__base_bash_libs_list_result_name=(\"\${__base_bash_libs_list_unique[@]}\")" + if ((${#__base_bash_libs_list_unique[@]} > 0)); then + eval "$__base_bash_libs_list_result_name=(\"\${__base_bash_libs_list_unique[@]}\")" + else + eval "$__base_bash_libs_list_result_name=()" + fi } base_list_length() {