linux shell常量 bash-自动将上次执行的命令的输出捕获到变量中



shell命令输出到变量 (16)

我希望能够在后续命令中使用上次执行的命令的结果。 例如,

$ find . -name foo.txt
./home/user/some/directory/foo.txt

现在让我们说我想要能够在编辑器中打开文件,或者删除它,或者用它做其他事情,例如

mv <some-variable-that-contains-the-result> /some/new/location

我该怎么做? 也许使用一些bash变量?

更新:

为了澄清,我不想手动分配东西。 我所追求的就像内置的bash变量,例如

ls /tmp
cd $_

$_保存了前一个命令的最后一个参数。 我想要类似的东西,但最后一个命令的输出。

最终更新:

塞思的答案工作得很好。 记住几件事情:

  • 不要忘记在第一次尝试解决方案时touch /tmp/x
  • 如果最后一条命令的退出代码成功,结果将被保存

Answer #1

用反引号捕获输出:

output=`program arguments`
echo $output
emacs $output

Answer #2

如果你想要的是重新运行你的最后一个命令并获得输出,一个简单的bash变量就可以工作:

LAST=`!!`

那么你可以在输出上运行你的命令:

yourCommand $LAST

这将产生一个新的过程并重新运行你的命令,然后给你输出。 这听起来像你真的想成为命令输出的bash历史文件。 这意味着您将需要捕获bash发送到您的终端的输出。 你可以写一些东西来观察必要的/ dev或/ proc,但这很麻烦。 你也可以在你的词汇和bash之间创建一个“特殊管道”,在中间的一个tee命令中重定向到你的输出文件。

但这两种都是一种很好的解决方案。 我认为最好的办法就是terminator ,这是一个更加现代化的输出日志记录终端。 只需检查您的日志文件中的最后一个命令的结果。 类似于上面的bash变量会使这更简单。


Answer #3

我通常做这里的其他人所建议的......没有作业:

$find . -iname '*.cpp' -print
./foo.cpp
./bar.cpp
$vi `!!`
2 files to edit

如果你喜欢,你可以更喜欢:

$grep -R "some variable" * | grep -v tags
./foo/bar/xxx
./bar/foo/yyy
$vi `!!`

Answer #4
find . -name foo.txt 1> tmpfile && mv `cat tmpfile` /path/to/some/dir/

是另一种方式,虽然很脏。


Answer #5

Bash是一种丑陋的语言。 是的,您可以将输出分配给变量

MY_VAR="$(find -name foo.txt)"
echo "$MY_VAR"

但更好的希望你最难find只返回一个结果,并且结果中没有任何“奇怪”的字符,比如回车或换行符,因为它们在分配给Bash变量时将被无声修改。

但使用它时,最好小心引用你的变量!

最好直接对文件进行操作,例如使用find-execdir (参考手册)。

find -name foo.txt -execdir vim '{}' ';'

要么

find -name foo.txt -execdir rename 's/\.txt$/.xml/' '{}' ';'

Answer #6

在执行完命令并确定要将结果存储在一个变量中后,有一种方法可以实现:

$ find . -name foo.txt
./home/user/some/directory/foo.txt
$ OUTPUT=`!!`
$ echo $OUTPUT
./home/user/some/directory/foo.txt
$ mv $OUTPUT somewhere/else/

或者,如果您事先知道要将结果存入变量,则可以使用反引号:

$ OUTPUT=`find . -name foo.txt`
$ echo $OUTPUT
./home/user/some/directory/foo.txt

Answer #7

我有类似的需求,我想在最后一个命令的输出中使用下一个命令的输出。 很像| | (管)。 例如

$ which gradle 
/usr/bin/gradle
$ ls -alrt /usr/bin/gradle

到像 -

$ which gradle |: ls -altr {}

解决方案:创建此自定义管道。 真的很简单,使用xargs -

$ alias :='xargs -I{}'

基本上没有为xargs创建一个简短的手,它像魅力一样工作,而且非常方便。 我只是在.bash_profile文件中添加别名。


Answer #8

你可以在你的bash配置文件中设置以下别名:

alias s='it=$($(history | tail -2 | head -1 | cut -d" " -f4-))'

然后,通过在任意命令后键入's',可以将结果保存到shell变量'it'中。

所以示例用法是:

$ which python
/usr/bin/python
$ s
$ file $it
/usr/bin/python: symbolic link to `python2.6'

Answer #9

Disclamers:

  • 这个答案是半年后的:D
  • 我是一个沉重的tmux用户
  • 你必须在tmux中运行你的shell才能工作

在tmux中运行交互式shell时,可以轻松访问当前在终端上显示的数据。 我们来看看一些有趣的命令:

  • tmux capture-pane :这一个将显示的数据复制到一个tmux的内部缓冲区。 它可以复制当前不可见的历史记录,但我们现在对此不感兴趣
  • tmux list-buffers :显示关于捕获缓冲区的信息。 最新的将有数字0。
  • tmux show-buffer -b(缓冲区号) :这将打印终端上给定缓冲区的内容
  • tmux paste-buffer -b(buffer num) :它将给定缓冲区的内容粘贴为输入

对我来说,我设置了一个简单的别名: alias L="tmux capture-pane; tmux showb -b 0 | tail -n 3 | head -n 1" ,现在每次我需要访问最后一行时,我只需使用$(L)即可获得它。

这与程序使用的输出流(stdin或stderr),打印方法(ncurses等)以及程序的退出代码无关 - 只需显示数据。


Answer #10

这很容易。 使用反引号:

var=`find . -name foo.txt`

然后你可以在将来的任何时候使用它

echo $var
mv $var /somewhere

Answer #11

你可以使用!!:1。 例:

~]$ ls *.~
class1.cpp~ class1.h~ main.cpp~ CMakeList.txt~ 

~]$ rm !!:1
rm class1.cpp~ class1.h~ main.cpp~ CMakeList.txt~ 


~]$ ls file_to_remove1 file_to_remove2
file_to_remove1 file_to_remove2

~]$ rm !!:1
rm file_to_remove1

~]$ rm !!:2
rm file_to_remove2

Answer #12

有多种方法可以做到这一点。 一种方法是使用v=$(command)将命令的输出分配给v 。 例如:

v=$(date)
echo $v

你也可以使用反引号。

v=`date`
echo $v

Bash初学者指南

当使用旧式反向引用替换形式时,除了后面跟有“$”,“`”或“\”之外,反斜杠将保留其字面含义。 第一个反斜杠前面没有反斜杠会终止命令替换。 当使用“$(COMMAND)”形式时,括号之间的所有字符构成命令; 没有人专门处理。

编辑:在问题的编辑后,似乎这不是OP正在寻找的东西。 据我所知,最后一个命令的输出没有像$_这样的特殊变量。


Answer #13

这是一个非常糟糕的解决方案,但似乎大部分时间都适用。 在测试过程中,我注意到它在命令行上获取^ C时有时效果不佳,尽管我稍微调整了它以表现得更好一些。

这种黑客攻击只是一种交互模式,我相信我不会向任何人推荐它。 后台命令可能会导致比正常情况下更少定义的行为。 其他答案是以编程方式获得结果的更好方法。

这就是说,这里是“解决方案”:

PROMPT_COMMAND='LAST="`cat /tmp/x`"; exec >/dev/tty; exec > >(tee /tmp/x)'

设置此bash环境变量并根据需要发出命令。 $LAST通常会有你想要的输出:

startide seth> fortune
Courtship to marriage, as a very witty prologue to a very dull play.
                -- William Congreve
startide seth> echo "$LAST"
Courtship to marriage, as a very witty prologue to a very dull play.
                -- William Congreve

Answer #14

我不知道任何自动执行此操作的变量。 除了复制粘贴结果之外,你可以重新运行你刚刚做的任何事情,例如

vim $(!!)

哪里!! 是历史扩张意思是'前一个命令'。

如果你期望有一个空格或其他字符的文件名可能会阻止正确的参数解析,请引用结果( vim "$(!!)" )。 如果不加引号,只要不包含空格或其他shell解析令牌,就可以一次打开多个文件。


Answer #15

我想你可能会破解一个解决方案,它涉及到将shell设置为包含以下内容的脚本:

#!/bin/sh
bash | tee /var/log/bash.out.log

然后,如果你设置$PROMPT_COMMAND输出一个分隔符,你可以编写一个辅助函数(也许称为_ )来获取该日志的最后一个块,所以你可以像这样使用它:

% find lots*of*files
...
% echo "$(_)"
... # same output, but doesn't run the command again

Answer #16

这并不是严格意义上的bash解决方案,但您可以使用sed的管道来获取前一个命令输出的最后一行。

首先让我们看看我在文件夹“a”

[email protected]::~$ find a
a
a/foo
a/bar
a/bat
a/baz
[email protected]::~$ 

然后,你用ls和cd的例子会变成sed&piping变成这样的东西:

[email protected]::~$ cd `find a |sed '$!d'`
[email protected]::~/a/baz$ pwd
/home/rasjani/a/baz
[email protected]::~/a/baz$

所以,真正的魔法发生在sed上,你将任何命令输出到sed中,sed打印最后一行,你可以用它作为参数。 或者你也可以把它和xargs结合起来。 (shell中的“man xargs”是你的朋友)





command-line