有人能帮助我理解下面的代码段吗?
set -- ${BACKUPDIR}/backup-???.tgz
lastname=${!#}
backupnr=${lastname##*backup-}
backupnr=${backupnr%%.*}
backupnr=${backupnr//\?/0}
backupnr=$[10#${backupnr}]
我在这个备份脚本中找到了它 https://wiki.ubuntuusers.de/Skripte/inkrementelles_Backup/ 它用于获取上次存储的备份的文件名编号。备份的文件名为“backup-ccc.tgz”,其中 ccc 是一个三位数,每次创建新备份时都会递增。
我理解第三行和第四行,它们截断了文件名的其余部分,只留下了需要的数字部分。我不明白前两行是如何工作的。我读了 set 的手册页,但现在我比以前更困惑了。这个命令是set -- filename
做什么的?还有,存储在 lastname 中的选项 ${!#} 到底是做什么的。我认为 ${} 是取消引用给定的参数,但是选项 !# 指向哪个参数?
其次,我不明白为什么我需要第 5 行的命令。据我所知,这用于将变量 backupnr 中存储的所有问号替换为 0,但为什么要这样做?如果之前的命令中没有错误,则 backupnr 应该是一个三位数,如果出现错误并且变量的内容已损坏,则您无法知道 backupnr 的实际值是多少。所以如果我想扫描损坏,为什么我不必扫描所有非数字的内容,而只需扫描问号?这可能与前两行发生的事情有某种关联吗?
答案1
set
通常用于设置位置参数($1
、$2
、$3
等,通常作为脚本的参数提供)。通过使用这些参数,我们可以获得一种简单的计数方法$#
,通过变量存储设置的位置参数的数量。
?
是匹配任意单个字符的通配符,因此???
可以匹配任意三个字符的组合。
组合:set -- ${BACKUPDIR}/backup-???.tgz
将每个名为 的文件backup-xxx.tgz
(其中xxx
为任意三个字符)设置为参数。
${!#}
,用途变量间接引用:
如果参数的第一个字符是感叹号 (!),则它会引入一个变量间接层。Bash 使用由参数其余部分形成的变量的值作为变量的名称;然后扩展此变量,并在其余替换中使用该值,而不是参数本身的值。这称为间接扩展。
因为$#
,也就是删除后得到的!
,是参数的数量(以及最后一个参数的数量),${!#}
所以这是一种获取最后一个参数的简单方法。
至于命令 5,当没有匹配的文件时会发生什么?
$ bash -c 'set -- backup-???.tgz; echo "$@"'
backup-???.tgz
shell 不会改变该词,所以现在我们只有一个文字backup-???.tgz
。作者通过将 替换为 来处理这种极端情况?
,0
以标记第一个备份文件。