让我用一个例子来解释一下:
我有一行在我的中声明了别名~/.bashrc
:
> grep lsdir ~/.bashrc
alias lsdir='ls -d */'
我刚刚将此行添加到我的 bashrc 中,因此别名尚未添加到我当前的会话环境中。由于某些配置原因,我也不想重新获取所有 bashrc 的源代码,这就是为什么我想简单地单独运行这个 grep 行。
出于好奇和教育的目的,我尝试着不用手动写下来,但没有成功。
我试过这个:
> $(grep lsdir ~/.bashrc)
bash: alias: -d: not found
bash: alias: */': not found
或这个:
> "$(grep lsdir ~/.bashrc)"
bash: alias lsdir='ls -d */': No such file or directory
甚至这个:
> $("grep lsdir ~/.bashrc")
bash: grep lsdir ~/.bashrc: No such file or directory
但没有一个奏效。有什么办法可以实现这一点吗?
答案1
你可以使用流程替代仅获取匹配的行:
source <(grep lsdir ~/.bashrc)
答案2
我找到了答案:
关键是使用内置的eval
.这样做将实现所需的行为(更准确地说,在我们登录的实际 shell 中运行命令,而不是在子 shell 中):
> eval "$(grep lsdir ~/.bashrc)"
> type lsdir
lsdir is aliased to `ls -d */'
答案3
虽然现有的答案提供了可行的解决方案,但它们都没有解释为什么原始命令$(grep lsdir ~/.bashrc)
不起作用。
事实上,shell 在替换过程中对命令做了有限的工作:您得到了单词分割,但没有引号处理:
pi@raspberrypi:~ $ echo 'a'
a
pi@raspberrypi:~ $ echo "echo 'a'"
echo 'a'
pi@raspberrypi:~ $ $(echo "echo 'a'")
'a'
正如您在最后一行中看到的,在命令 ( ) 和参数 ( )echo 'a'
中正确分割,但参数本身没有经过引号处理,因此引号保持不变。顺便说一句,当你尝试时,几乎会发生同样的事情echo
'a'
将 shell 命令存储在变量中。
在您的情况下,alias lsdir='ls -d */'
被分为命令、alias
其参数和两个意想不到的lsdir='ls
附加参数(-d
和*/'
) 。alias
允许重新运行所有命令处理(包括引号处理)的一种自然解决方案是使用eval
, 并且答案之一已经提到。
答案4
你可以只使用一个变量作为输出
torun=$(some commands | adapting/parsing results #be aware of multiline returns too)
${torun} # call the generated command
正如这里由于讨论而提到的,在大多数情况下,好主意是您必须使用管道添加一个子命令来解析/解析命令的结果,以避免在将变量应用${torun}
为命令时出现转义字符或引用问题
简而言之:不要忘记使字符串成为变量定义行内的可用命令。
典型的 :
torun=$( command | sed '....;.....;....' ) #or awk or any string management tools