Bash 中字符串变量中带 ~ 和不带 ~ 有什么区别?

Bash 中字符串变量中带 ~ 和不带 ~ 有什么区别?

我正在使用一个点文件管理软件,名为点滴. 使用名为 的配置文件.env,内容如下:git_folder="~/code/Git".

还可以在首次使用此 dotfile 工具之前使用脚本对其进行设置,如下所示,

#!/bin/bash

env1="~/Dropbox/.env"
env2="/mnt/d/Dropbox/.env"

if [ -f $env1 ]; then
    echo "Found dotdrop env file, installing dotfiles..."
    source $env1
    eval $(grep -v "^#" $env1) dotdrop --cfg=${git_folder}/dotfiles/config.yaml install
elif [ -f $env2 ]; then
    echo "Found dotdrop env file, installing dotfiles..."
    source $env2
    eval $(grep -v "^#" $env2) dotdrop --cfg=${git_folder}/dotfiles/config.yaml install
else echo "Pls sync environment files first!"
fi

如果我将配置文件存储在~/Dropbox/.env,当我运行脚本时,我就会得到"Pls sync environment files first!"(如果需要条件则运行)。如果配置文件存储在/mnt/d/Dropbox/.env,脚本将经历 elif 条件,这是预期的。

找到原因,直到我在 dubug 模式下运行脚本,并得到差异:

➜  scripts git:(master) ✗ bash -x dotdrop_setup.sh 
+ env1='~/Dropbox/.env'
+ env2=/mnt/d/Dropbox/.env
+ '[' -f '~/Dropbox/.env' ']'
+ '[' -f /mnt/d/Dropbox/.env ']'
+ echo 'Pls sync environment files first!'
Pls sync environment files first!

~所以,我认为和之间的区别/home/user就是原因。

当我更改~/home/roach(roach是用户名)后,它就可以工作了。

➜  scripts git:(master) ✗ bash -x dotdrop_setup.sh
+ env1=/home/roach/Dropbox/.env
+ env2=/mnt/d/Dropbox/.env
+ '[' -f /home/roach/Dropbox/.env ']'
+ echo 'Found dotdrop env file, installing dotfiles...'
Found dotdrop env file, installing dotfiles...
+ source /home/roach/Dropbox/.env
++ git_folder='~/code/Git'
++ grep -v '^#' /home/roach/Dropbox/.env
+ eval git_folder='~/code/Git'
++ dotdrop '--cfg=~/code/Git/dotfiles/config.yaml' install
     _       _      _
  __| | ___ | |_ __| |_ __ ___  _ __
 / _` |/ _ \| __/ _` | '__/ _ \| '_ |
 \__,_|\___/ \__\__,_|_|  \___/| .__/  v0.22.0
                               |_|


0 dotfile(s) installed.

调试显示''环绕声+ env1='~/Dropbox/.env'已被删除,我认为这就是原因。

但,为什么


附加问题,

alias dotdrop="eval $(grep -v "^#" $env1) /usr/bin/dotdrop --cfg=${git_folder}/dotfiles/config.yaml install"是一个配置添加到bashrczshrc等等。如果我直接将它添加到我的脚本中,它不起作用!

最后发现我必须添加source $env

所以为什么它在 bashrc 文件中工作吗?

答案1

~是主目录的快捷方式,但仅当它出现在字符串的开头时外部报价。赋值运算符右侧的开头是字符串的开头,因此env1=~/Dropbox/.env可以工作(或env1=~"/Dropbox/.env"任何数量的变体)。它设置env1/home/roach/Dropbox/.env.但env1="~/Dropbox/.env"设置env1为确切的 string ,它作为文件名在当前目录~/Dropbox/.env中查找具有单字符名称的目录。~

波形符是缩写,而不是通配符。$env1外部引号会扩展 值中的通配符env1,但不会扩展波浪号,因为波浪号不是通配符。

您也可以使用env1="$HOME/Dropbox/.env".这相当于env1=~/Dropbox/.env.双引号内的字符$(美元)具有特殊含义(与引号外的含义相同):它启动变量替换(或命令或算术替换)。~另一方面,当字符(波形符)位于引号(甚至双引号)内时,它只是一个普通字符。


至于别名,它在 bash 脚本中不起作用的原因是 bash 默认情况下不会在脚本中扩展别名。除非您在脚本中包含或获取别名的定义,否则它在任何脚本中都不起作用,因为别名是每个 shell 实例的属性。它们不是流程环境的一部分。

别名在第二个脚本中起作用的原因是 dotdrop 本身在读取其配置值时会扩展波浪号。

相关内容