Bash变量赋值解释 {var:=0} {var:-0}?

3
我是一名bash初学者,正在阅读书籍和手册以进一步学习。我在一本书中发现了以下脚本,它计算总大小并展示了命令替换的用法。我不理解包含{totalsize:=0}{size:-0}{totalsize-unset}的部分。请问有人可以解释一下吗?
乍一看,它看起来像一个数组,但这里的操作符:=:-是干什么的?totalsize是包含值的变量,但是当我运行echo ${totalsize-unset}时,它确实返回了PWD中文件大小的总和。这个-unset是一种内置的东西吗?
$ while read perms links owner group size month day time file
> do
>  printf "%10d %s\n" "$size" "$file"
>  totalsize=$(( ${totalsize:=0} + ${size:-0} ))
> done < <(ls -l *)
$ echo ${totalsize-unset}

2
我不是一个完美的势利眼。看,说真的,你的命令非常危险,因为它允许执行任意代码。例如,一个包含换行符的文件名,在换行符后面是形如a[$(...)]的第五个字段,其中...是任何命令,那么这个命令将被执行。不相信我?在你的目录中执行以下操作:touch $'\n_ _ _ _ a[$(echo>gniourf\ \'hello\ Donbhupi\')]'。它会创建一个奇怪的文件名。无论如何,然后运行你的命令。你会发现你有一个新文件,叫做gniourf,里面包含了一条消息。 - gniourf_gniourf
1
@gniourf_gniourf,非常感谢您对此的贡献。我想相信这让我变得更聪明了一些。我试图分析您让我“touch”的特殊文件名:\n将解析器发送到下一行,然后名称中的五个空格将其移动为“size”可读,并且剩下的内容无法作为数字打印,但是是什么使其作为命令执行的呢?如果将其作为整数传递给算术加法,那么它是某种数组脚本吗? 还有,@John1024在他的第一条评论中提供了有关解析“ls”的链接。 - Donbhupi
1
命令可执行的原因是,在算术上下文中,Bash 尽可能地进行解引用。例如:a=b b=c c=42; echo $((a)) 将输出 42。为了好玩,您可以尝试 a=b b=a; echo $((a)) 或者甚至是 a=a; echo $((a))。现在来看数组:a=(); b='a[$(ls)]'; echo "b=$b"; echo "\$((b))=$((b))"。这将执行 ls 命令。这是因为 Bash 需要知道您正在使用哪个键,所以它尝试对其进行解引用... 但为此它会执行 $(ls) - gniourf_gniourf
1
关于您的命令 zcat $( ls -tr /var/log/apt/history.log*.gz ):由于日志文件具有受控名称,所以它可能是可以接受的。在这种情况下,问题不在于任意代码执行,而在于路径名扩展和单词拆分:它只会破坏命令。但是,由于您相当确定文件具有受控名称,因此这是可以接受的。不过,您可以像这样强制执行检查:( shopt -s extglob failglob; zcat $(ls -tr /var/log/apt/history.log+([[:digit:]]).gz ) ; cat /var/log/apt/history.log ) | egrep '^Commandline:' - gniourf_gniourf
1
@gniourf_gniourf花了我很长时间才理解算术调整,但它确实很有趣和引人入胜,也许是我在SO上学到的最好的东西。感谢您提供的shopt部分。您是一位专业人士,如果我戴帽子的话,我会脱下我的帽子向您致敬。希望您有一个网站、博客或一本书! - Donbhupi
显示剩余16条评论
1个回答

3

好的,让我们公平一点,这是一个人为制造的例子,旨在演示进程替换,并没有提醒这里突出的安全风险。很不幸。

在Bash中,变量可以根据此处描述的语法进行操作或扩展:

http://www.tldp.org/LDP/abs/html/parameter-substitution.html#PARAMSUBREF

上述脚本的意图是,如果totalsize没有值,则将其赋为零。在循环的第一次迭代中,totalsize将没有值。相反,将使用零进行计算。
有许多方法可以实现相同的结果。使用du -h命令更为合理。
首先运行man du并了解此命令的作用(它估计文件空间使用情况)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接