我知道这可能是以前问过的,但是我在Google找不到。
给定
- Linux内核
- 没有可更改$ HOME的配置
- 重击
会~ == $HOME是真的吗?
echo "~"和echo "$HOME"。
~或$HOME。:P
我知道这可能是以前问过的,但是我在Google找不到。
给定
会~ == $HOME是真的吗?
echo "~"和echo "$HOME"。
~或$HOME。:P
Answers:
需要理解的重要一点是,~扩展是Shell(在某些Shell中)的功能,它不是魔术字符,而意味着它在任何位置都使用了主目录。
它被扩展(由外壳程序(用于解释命令行的应用程序)),就像$var在执行命令之前在外壳程序命令行中使用某些情况下,将其扩展到其值一样。
该功能最初出现在1970年代后期的C壳中(Bourne壳没有它,或者它的前身Thompson壳也没有),后来又被添加到Korn壳中(在Bourne壳的基础上建立了一个更新的壳) 80年代)。最终它由POSIX进行了标准化,现在可在包括非POSIX的大多数shell中使用fish。
由于它在shell中的使用如此广泛,因此某些非shell应用程序也将其视为主目录。这是许多应用的情况下,它们的配置文件或他们自己的命令行(mutt,slrn,vim...)。
bash特别是(它是GNU项目的外壳,并在许多基于Linux的操作系统中广泛使用),当调用为时sh,主要遵循POSIX有关~扩展的规则,并且在POSIX未指定的区域中,其行为与Korn shell(of它是部分克隆)。
尽管$var在大多数地方都进行了扩展(单引号内除外),~但事后才想到扩展仅在某些特定条件下才扩展。
在列表上下文中(在需要字符串的情况下)使用自己的参数扩展时。
以下是一些扩展示例bash:
cmd arg ~ other argvar=~var=x:~:x(由POSIX要求,用于变量一样PATH,MANPATH...)for i in ~[[ ~ = text ]][[ text = ~ ]](~在AT&T 中被视为一种模式的扩展,ksh但从bash4.0开始就没有)。case ~ in ~) ...${var#~} (尽管不在其他shell中)cmd foo=~(尽管不是当用调用时sh,并且仅当其左侧的=形状像未加引号的bash变量名时那样)cmd ~/x (显然是POSIX要求的)cmd ~:x(但不是x:~:x或x-~-x)a[~]=foo; echo "${a[~]} $((a[~]))" (不在其他shell中)以下是一些未扩展的示例:
echo "~" '~'echo ~@ ~~(另请注意,这~u是为了扩展到user的主目录u)。echo @~(( HOME == ~ )), $(( var + ~ ))extglob:(case $var in @(~|other))...虽然case $var in ~|other)可以)。./configure --prefix=~(因为--prefix不是有效的变量名)cmd "foo"=~(在中bash,由于引号)。sh:export "foo"=~,env JAVA_HOME=~ cmd...至于扩展到什么:~仅扩展到HOME变量的内容,或者在未设置变量时,扩展到帐户数据库中当前用户的主目录(作为扩展,因为POSIX未定义该行为)。
应该注意的是,在ksh88和bash4.0之前的版本中,波浪线扩展在列表上下文中进行了遍历(文件名生成):
$ bash -c 'echo "$HOME"'
/home/***stephane***
$ bash -c 'echo ~'
/home/***stephane*** /home/stephane
$ bash -c 'echo "~"'
~
在通常情况下,这应该不成问题。
请注意,由于它已展开,因此与其他形式的展开一样,会出现相同的警告。
cd ~
如果$HOME以开头-或包含..组件,则不起作用。因此,即使严格意义上来说,即使几乎不可能产生任何改变,也应该这样写:
cd -P -- ~
甚至:
case ~ in
(/*) cd -P ~;;
(*) d=~; cd -P "./$d";;
esac
(以覆盖$HOMElike -,+2...的值)或简单地:
cd
(因为cd无需任何参数即可将您转到主目录)
其他外壳具有更高级的~扩展。例如,在中zsh,我们有:
~4,~-,~-2(竣工)用于扩大在目录栈目录(您已获得的地方cd到前)。~something扩展。在任何系统上的任何版本的Bash中,yes。~单独定义的术语扩展为:
$ HOME的值
因此它将始终$HOME与当前shell相同。还有其他几个波浪号扩展名,例如~userfor user的主目录,但单引号~本身总是会扩展为"$HOME"。
需要注意的是该行为的~,并$HOME在某些情况下是不同的:尤其是,如果$HOME包含空格(或其他IFS字符),然后$HOME(不带引号)将扩大到多个字,而~始终是一个字。~等效于"$HOME"(引用)扩展。
关于您的特定问题:
[[ $HOME == ~ ]]
总是正确的,因为[[ 抑制了单词拆分。[[ ~ == $HOME ]可能不是,如果HOME有模式匹配在里面的人物,但[[ ~ == "$HOME" ]](即引用"$HOME")始终是真实的。对于HOME包含空格或特殊字符的值,在单括号内使用它可能是语法错误。对于任何明智的主目录配置~,"$HOME"它们都是相同的,并且比较相等。
StéphaneChazelas在注释中提到了一种情况,其中~并$HOME提供了不同的值:如果您使用unset HOME,那么当您使用~Bash时,它将调用getpwuid从密码数据库中读取一个值。您无需更改配置的情况就排除了这种情况$HOME,但出于完整性考虑,我在这里将其提及。
/bin/sh可能不是bash。我不知道,Posix的sh规范讲述~
~。~不在Thomson或Bourne外壳中(当时可作为/bin/sh)。这不是在rc或其衍生物(使用它的其他东西)
bash,如果HOME未设置,~则从passwd数据库扩展到用户的主目录。因此,这种情况下~可能无法扩展为的值$HOME。
bash在bash4用来在波浪号扩展上执行glob之前(try HOME='/*' bash -c 'echo /*')。因此HOME=/*; [ "$HOME" = ~ ]会在那里返回错误。
~它将等同$HOME于任何POSIX环境。但我可能是错的。