波浪号扩展在 shell 变量中如何工作?

波浪号扩展在 shell 变量中如何工作?

我在测试脚本时发现了一些有趣的事情。

如果我运行,我可以从 shell 手动 ls 我的目录

$ ls ~/db_backups/
test1  test2
$ 

但是,如果我使用波浪号为 shell 变量分配一个目录位置,则它不起作用。我用单引号和双引号尝试过。

$ backupfolder='~/db_backups'
$ echo $backupfolder
~/db_backups
$ ls $backupfolder
ls: cannot access '~/db_backups': No such file or directory
$ 

shell 变量内的波形符替换发生了什么?为什么我不能像手动使用目录名称中的波浪号那样通过变量来 ls 目录?

答案1

当波形符是变量扩展结果的一部分时,shellbash将不会扩展。~不带引号的波形符前缀(~~+~username对于当前用户名为username)仅在位于单词开头或紧跟在=或后面:(可选地后跟/和 其他路径元素)时扩展到当前用户的主目录。

在您的情况下,在分配给您的变量时进行扩展会更容易backupfolder。如果您留下波形符,就会发生这种情况未引用的(既不使用单引号也不使用双引号):

backupfolder=~/db_backups
ls "$backupfolder"

...或者如果您$HOME改为使用(不带单引号):

backupfolder=$HOME/db_backups
ls "$backupfolder"

在这两个赋值中,shell 会将赋值运算符右侧的值扩展为db_backups当前用户主目录中调用的路径名。

一般来说,$HOME在脚本中使用通常更容易,并将其留给~交互式会话,它可以作为方便的快捷方式。该HOME变量始终表现为多变的

答案2

简而言之,您需要显式且不带引号的~user/(或~/),并且它不能是变量扩展的结果。

你需要backupfolder=~/'db_backups'有一个成功的ls $backupfolder

长描述

波浪线扩展可能发生的唯一方法是拥有一个实际的未引用的 ~最多也未引用的 /,或字符串的结尾。

Anecho ~cris/'one space'将扩展波浪号(和用户名),但如果没有实际的波浪号,~则不会扩展波浪号。有趣的是,这样的命令需要引用,因为路径值中包含一个空格one space

此外,如果此列表中的任何扩展(在 bash 中的大括号扩展后扩展):波形符扩展、参数和变量扩展、算术扩展和命令替换被执行(以从左到右的方式完成),列表中的其他单词都不会被重新应用于同一个单词(所有都同时发生,有点)。

然后,大括号扩展(要发生的第一个扩展)可以通过列表进行额外扩展,并且(最后两个扩展)单词分割和路径名扩展将应用于前面步骤的结果。例如,这将扩展三个变量:

$ echo $HIST{FILE,FILESIZE,SIZE}
/home/cris/.bash_history 2000 1000

大括号扩展的结果通过变量扩展重新扩展。但是变量扩展不会被另一个扩展重新扩展:

$ b='$((2+2))'; echo $b
$((2+2))

简而言之,您需要显式且不带引号的~user/(或~/),并且它不能是变量扩展的结果。

请注意,算术展开不属于“仅一次展开”规则。在算术展开式中,展开式可能会递归几个步骤。例如:

$ a=b; b=c; c=d; d=23; echo $(($a))
23

请注意,我没有列出,process substitution但也应该添加。

相关内容