首页 > 解决方案 > 如何使 bash 'pop' 和 'shift' 函数实际返回弹出或移动的项目?

问题描述

跑步

$ echo $BASH_VERSION
4.3.42(1)-release

给定这两个功能:

ashift ()
{
    declare -n arr;arr="$1"
    ((${#arr[@]} == 0)) && return
    echo "${arr[0]"}
    arr=("${arr[@]:1}")
}
apop ()
{
    declare -n arr="$1";shift
    ((${#arr[@]} == 0)) && return
    echo "${arr[-1]}"
    arr=("${arr[@]:0:$((${#arr[@]}-1))}")
}

使用它们的“自然”方式是

declare -a thearray
thearray=(a b c d e f g)
p=$(apop thearray)
s=$(ashift thearray)
echo "p=$p, thearray=${thearray[@]}, s=$s"

但是,输出不是您所期望的:

p=g, thearray=a b c d e f g, s=a

那是因为(我认为)我们在子shell中运行ashiftandapop来捕获输出。如果我没有捕获输出:

declare -a thearray
thearray=(a b c d e f g)
apop thearray
ashift thearray
echo "thearray=${thearray[@]}"

输出(与命令混合)是

g
a
thearray=b c d e f

那么,有谁知道我如何在当前进程中运行apopand命令并捕获输出?ashift


注意:为了完整起见,这些工作是因为没有捕获,所以你永远不要在子shell中运行它们:

aunshift ()
{
    declare -n arr;arr="$1";shift
   arr=("$@" "${arr[@]}")
}
apush ()
{
    declare -n arr;arr="$1";shift
    arr+=("$@")
}

标签: arraysbashsubshell

解决方案


假设您对以下'API'4 项操作没有问题:

apush array value1 value2 value3 ...
ashift array value1 value2 value3 ...
apop array var1 var2 var3        # Extracted values stored in variables
aunshift array var1 var2 var3    # Extract values stored in variables

可以使用 bash 引用变量(声明 -n)。

#! /bin/bash

function apush {
    declare -n _array=$1
    shift
    _array+=("${@}")
}

function apop {
    declare -n _array=$1
    shift
    declare _n=0
    for _v ; do
        declare -n _var=$_v
        let ++_n
        _var=${_array[-_n]}
    done
    array=("${_array[@]:0:$((${#_array[@]}-_n))}")
}

使用以下测试用例

A=()
apush A B1 B2 B3
apush A C1 C2 C3
echo "S1=${A[*]}"
apop A X1 X2 X3
echo "X1=$X1, X2=$X2, X3=$X3, A=${A[*]}"

输出

S1=B1 B2 B3 C1 C2 C3
X1=C3, X2=C2, X3=C1, A=B1 B2 B3

同样,ashift、aunshift 可以按照类似的模式实现。

另请注意:由于 bash 引用的工作方式,无法访问与局部变量同名的变量。如果使用与本地名称匹配的变量调用函数,则会产生错误。修改函数以使用_变量前缀,以减少出现此问题的机会。

apush _array ABC

Output:
bash: declare: warning: array: circular name reference
bash: warning: array: circular name reference

推荐阅读