警告:a:bash 中使用递归函数的合并排序中的循环名称引用

warning: a: circular name reference in Merge Sort using recursive functions in bash

我正在尝试在 bash 中基于 C 语言实现合并排序,这是我的代码:

#!/bin/bash

function merge() {
    local -n a=
    local low=
    local mid=
    local high=
    for ((l1 = low, l2 = mid + 1, i = low; l1 <= mid && l2 <= high; i++)); do
        if [[ a[$l1] -le a[$l2] ]]; then
            b[$i]=${a[((l1++))]}
        else
            b[$i]=${a[((l2++))]}
        fi
    done
    while [[ $l1 -le $mid ]]; do
        b[((i++))]=${a[((l2++))]}
    done
    while [[ $l2 -le $high ]]; do
        b[((i++))]=${a[((l2++))]}
    done
    for ((i = low; i <= high; i++)); do
        a[$i]=${b[$i]}
    done
}

function sort() {
    local -n a=
    local low=
    local high=
    echo "a=${a[*]}"
    echo "low=$low"
    echo "high=$high"

    if [[ $low < $high ]]; then
        mid=$(((low + high) / 2))
        sort a "$low" $mid
        sort a $((mid + 1)) "$high"
        merge a "$low" $mid "$high"
    else
        echo "${arr[@]}"
    fi
}

declare -a arr
echo "Enter the elements of the array: "
read -ra arr
len=${#arr[@]}
echo $len
sort arr 0 $((len - 1))

echo "Array after sort;"
echo "${arr[@]}"

执行后,我收到同样的错误垃圾邮件:

warning: a: circular name reference

完整日志:https://del.dog/error-log.txt

我的解释是,递归函数和 namerefs 在 bash 中并不齐头并进。有什么方法可以在 bash 中实现合并排序?

Namerefs 通过 name 引用变量。因此,这些引用不像 C 中的指针。相反,如果范围发生变化,namerefs 可能会引用一个与预期不同的变量。

这是您的问题的核心。

countdown() {
  local -n a=""
  if (( a > 0 )); then
    echo "$(( a-- ))"
    countdown a
  fi
}
b=3
countdown b

如果你执行countdown,你在第一级递归后会得到local -n a=a。要避免这个问题,只需使用 a (${!a} = b) 引用的全局变量的名称而不是 a 本身进行递归:

countdown() {
  local -n a=""
  if (( a > 0 )); then
    echo "$(( a-- ))"
    countdown "${!a}"
  fi
}
b=3
countdown b

tl;dr: 调用 sort/merge "${!a}" 而不是 sort/merge a.

顺便说一句: bash 数组的索引总是一个算术表达式。你可以写 a[i]=...... "${a[i++]}"。这里不需要$(( ... )))

另外,我想你想写 if (( low < high )) 而不是 if [[ $low < $high 因为 ...

When used with [[, the ‘<’ and ‘>’ operators sort lexicographically using the current locale

... 意思是 29 < 3.