arrays - 如何使 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中运行ashift
andapop
来捕获输出。如果我没有捕获输出:
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
那么,有谁知道我如何在当前进程中运行apop
and命令并捕获输出?ashift
注意:为了完整起见,这些工作是因为没有捕获,所以你永远不要在子shell中运行它们:
aunshift ()
{
declare -n arr;arr="$1";shift
arr=("$@" "${arr[@]}")
}
apush ()
{
declare -n arr;arr="$1";shift
arr+=("$@")
}
解决方案
假设您对以下'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
推荐阅读
- pvs-studio - 在 Linux 终端打印 PVS-Studio 分析的彩色日志
- c - 创建需要两个日期的 ac 程序并输出它们之间的天数
- java - 我使用 Math.floor() 的 Java 数学表达式为 0 而不是预期的数字,即使我的论文计算表明它应该是其他的
- r - 在 R 中使用 RCurl 下载 NASA 卫星数据
- apache-spark - 如何在 Glue 中控制 Parquet 文件的大小?
- javascript - 基于 .obj 模型的颜色
- django-models - 管理员没有注册地址类型怎么来(我使用 django)?
- javascript - 当 React 元素的文本更改时渲染 CSS 过渡
- c++ - 插入共享内存中的映射映射时出现编译器错误
- python - 不使用 ModelForm 上传图片