使用 Bash 自动将上一个命令的输出捕获到变量中?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5955577/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 00:53:53  来源:igfitidea点击:

Automatically capture output of last command into a variable using Bash?

linuxbashcommand-line

提问by armandino

I'd like to be able to use the result of the last executed command in a subsequent command. For example,

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

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

Now let's say I want to be able to open the file in an editor, or delete it, or do something else with it, e.g.

现在假设我希望能够在编辑器中打开文件,或者删除它,或者用它做其他事情,例如

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

How can I do it? Maybe using some bash variable?

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

Update:

更新:

To clarify, I don't want to assign things manually. What I'm after is something like built-in bash variables, e.g.

澄清一下,我不想手动分配东西。我所追求的是类似于内置的 bash 变量,例如

ls /tmp
cd $_

$_holds the last argument of the previous command. I want something similar, but with the output of the last command.

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

Final update:

最终更新:

Seth's answer has worked quite well. Couple of things to bear in mind:

赛斯的回答非常有效。需要牢记以下几点:

  • don't forget to touch /tmp/xwhen trying the solution for the very first time
  • the result will only be stored if last command's exit code was successful
  • touch /tmp/x第一次尝试解决方案时不要忘记
  • 仅当最后一个命令的退出代码成功时才会存​​储结果

采纳答案by Seth Robertson

This is a really hacky solution, but it seems to mostly work some of the time. During testing, I noted it sometimes didn't work very well when getting a ^Con the command line, though I did tweak it a bit to behave a bit better.

这是一个非常hacky的解决方案,但它似乎在某些时候大部分时间都有效。在测试期间,我注意到^C在命令行上获取 a 时有时效果不佳,尽管我确实对其进行了一些调整以使其表现得更好。

This hack is an interactive mode hack only, and I am pretty confident that I would not recommend it to anyone. Background commands are likely to cause even less defined behavior than normal. The other answers are a better way of programmatically getting at results.

这个 hack 只是一个交互模式的 hack,我非常有信心我不会向任何人推荐它。后台命令可能会导致比正常情况更不明确的行为。其他答案是以编程方式获得结果的更好方法。



That being said, here is the "solution":

话虽如此,这是“解决方案”:

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

Set this bash environmental variable and issues commands as desired. $LASTwill usually have the output you are looking for:

设置此 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

回答by Wes Hardaker

It's quite easy. Use back-quotes:

这很容易。使用反引号:

var=`find . -name foo.txt`

And then you can use that any time in the future

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

echo $var
mv $var /somewhere

回答by bandi

Capture the output with backticks:

使用反引号捕获输出:

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

回答by Daenyth

I don't know of any variable that does this automatically. To do something aside from just copy-pasting the result, you can re-run whatever you just did, eg

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

vim $(!!)

Where !!is history expansion meaning 'the previous command'.

!!历史扩展在哪里,意思是“上一个命令”。

If you expect there to be a single filename with spaces or other characters in it that might prevent proper argument parsing, quote the result (vim "$(!!)"). Leaving it unquoted will allow multiple files to be opened at once as long as they don't include spaces or other shell parsing tokens.

如果您希望有一个包含空格或其他字符的单个文件名,可能会阻止正确的参数解析,请引用结果 ( vim "$(!!)")。不加引号将允许一次打开多个文件,只要它们不包含空格或其他 shell 解析标记。

回答by taskinoor

There are more than one ways to do this. One way is to use v=$(command)which will assign the output of command to v. For example:

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

v=$(date)
echo $v

And you can use backquotes too.

你也可以使用反引号。

v=`date`
echo $v

From Bash Beginners Guide,

来自Bash 初学者指南

When the old-style backquoted form of substitution is used, backslash retains its literal meaning except when followed by "$", "`", or "\". The first backticks not preceded by a backslash terminates the command substitution. When using the "$(COMMAND)" form, all characters between the parentheses make up the command; none are treated specially.

当使用旧式反引号替换形式时,反斜杠保留其字面意义,除非后跟“$”、“`”或“\”。前面没有反斜杠的第一个反引号终止命令替换。使用“$(COMMAND)”形式时,括号之间的所有字符组成命令;没有被特殊对待。

EDIT: After the edit in the question, it seems that this is not the thing that the OP is looking for. As far as I know, there is no special variable like $_for the output of last command.

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

回答by Nate W.

Here's one way to do it after you've executed your command and decided that you want to store the result in a variable:

这是在您执行命令并决定要将结果存储在变量中后的一种方法:

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

Or if you know ahead of time that you'll want the result in a variable, you can use backticks:

或者,如果您提前知道需要将结果保存在变量中,则可以使用反引号:

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

回答by rlibby

Bash is kind of an ugly language. Yes, you can assign the output to variable

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

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

But better hope your hardest that findonly returned one result and that that result didn't have any "odd" characters in it, like carriage returns or line feeds, as they will be silently modified when assigned to a Bash variable.

但最好希望你最努力find只返回一个结果,并且该结果中没有任何“奇数”字符,如回车或换行符,因为它们在分配给 Bash 变量时会被静默修改。

But better be careful to quote your variable correctly when using it!

但是在使用变量时最好小心正确引用它!

It's better to act on the file directly, e.g. with find's -execdir(consult the manual).

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

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

or

或者

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

回答by halm

I usually do what the others here have suggested ... without the assignment:

我通常会按照其他人的建议去做……没有分配:

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

You can get fancier if you like:

如果你喜欢,你可以变得更漂亮:

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

回答by 0xC0000022L

As an alternative to the existing answers: Use whileif your file names can contain blank spaces like this:

作为现有答案的替代方案:while如果您的文件名可以包含这样的空格,请使用:

find . -name foo.txt | while IFS= read -r var; do
  echo "$var"
done

As I wrote, the difference is only relevant if you have to expect blanks in the file names.

正如我所写的,只有当您必须期望文件名中有空格时,差异才有意义。

NB:the only built-in stuff is not about the output but about the status of the last command.

注意:唯一的内置内容不是关于输出,而是关于最后一个命令的状态。

回答by ssapkota

By saying "I'd like to be able to use the result of the last executed command in a subsequent command", I assume - you mean the result of any command, not just find.

通过说“我希望能够在后续命令中使用上次执行的命令的结果”,我假设 - 您的意思是任何命令的结果,而不仅仅是查找。

If thats the case - xargsis what you are looking for.

如果是这样的话 - xargs就是你要找的。

find . -name foo.txt -print0 | xargs -0 -I{} mv {} /some/new/location/{}

find . -name foo.txt -print0 | xargs -0 -I{} mv {} /some/new/location/{}

OR if you are interested to see the output first:

或者,如果您有兴趣先查看输出:

find . -name foo.txt -print0

find . -name foo.txt -print0

!! | xargs -0 -I{} mv {} /some/new/location/{}

!! | xargs -0 -I{} mv {} /some/new/location/{}

This command deals with multiple files and works like a charm even if the path and/or filename contains space(s).

即使路径和/或文件名包含空格,此命令也可以处理多个文件并像魅力一样工作。

Notice the mv {} /some/new/location/{}part of the command. This command is build and executed for each line printed by earlier command. Here the line printed by earlier command is replaced in place of {}.

请注意命令的mv {} /some/new/location/{}部分。此命令是为较早命令打印的每一行构建和执行的。这里由较早的命令打印的行被替换为{}

Excerpt from man page of xargs:

摘自 xargs 的手册页:

xargs - build and execute command lines from standard input

xargs - 从标准输入构建和执行命令行

For more detail see man page: man xargs

有关更多详细信息,请参见手册页: man xargs