Bash 中是否可以将命令的输出作为实际的命令行来运行

Bash 中是否可以将命令的输出作为实际的命令行来运行

让我用一个例子来解释一下:

我有一行在我的中声明了别名~/.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

相关内容