ada*_*ncy 12 linux bash readline
让我用一个例子来解释一下:
我有一行在我的中声明了别名~/.bashrc:
> grep lsdir ~/.bashrc
alias lsdir='ls -d */'
Run Code Online (Sandbox Code Playgroud)
我刚刚将此行添加到我的 bashrc 中,因此别名尚未添加到我当前的会话环境中。由于某些配置原因,我也不想重新获取所有 bashrc 的源代码,这就是为什么我想简单地单独运行这个 grep 行。
出于好奇和教育的目的,我尝试着不用手动写下来,但没有成功。
我试过这个:
> $(grep lsdir ~/.bashrc)
bash: alias: -d: not found
bash: alias: */': not found
Run Code Online (Sandbox Code Playgroud)
或这个:
> "$(grep lsdir ~/.bashrc)"
bash: alias lsdir='ls -d */': No such file or directory
Run Code Online (Sandbox Code Playgroud)
甚至这个:
> $("grep lsdir ~/.bashrc")
bash: grep lsdir ~/.bashrc: No such file or directory
Run Code Online (Sandbox Code Playgroud)
但没有一个奏效。有什么办法可以实现这一点吗?
jes*_*e_b 23
您可以使用Process Substitution来仅获取匹配的行:
source <(grep lsdir ~/.bashrc)
Run Code Online (Sandbox Code Playgroud)
ada*_*ncy 13
我找到了答案:
关键是使用内置的eval. 这样做将实现所需的行为(更准确地说,在我们登录的实际 shell 中运行命令,而不是在子 shell 中):
> eval "$(grep lsdir ~/.bashrc)"
> type lsdir
lsdir is aliased to `ls -d */'
Run Code Online (Sandbox Code Playgroud)
Dmi*_*yev 10
虽然现有的答案提供了可行的解决方案,但它们都没有解释为什么原始命令$(grep lsdir ~/.bashrc)不起作用。
事实上,shell 在替换期间对命令执行了有限的工作:您得到了单词分割,但没有引号处理:
pi@raspberrypi:~ $ echo 'a'
a
pi@raspberrypi:~ $ echo "echo 'a'"
echo 'a'
pi@raspberrypi:~ $ $(echo "echo 'a'")
'a'
Run Code Online (Sandbox Code Playgroud)
正如您在最后一行中看到的,在命令 ( ) 和参数 ( )echo 'a'中正确分割,但参数本身没有经过引号处理,因此引号保持不变。顺便说一句,当您尝试将 shell 命令存储在变量中时,几乎会发生同样的事情。echo'a'
在你的例子中,alias lsdir='ls -d */'被分成命令,alias它的参数,以及两个意想不到的lsdir='ls附加参数(-d和*/') 。alias
允许重新运行所有命令处理(包括引号处理)的一种自然解决方案是使用eval, 并且答案之一已经提到。