有时,我想使用 cli 工具进一步处理/过滤命令行脚本的输出。我无法重新运行该命令,因为它需要很长时间或者不会再次产生相同的输出。
目前,我将输出粘贴到文本编辑器中的新文件中,保存它,然后使用cat
cli 将其通过管道传输到 tr、sed 和其他工具中。这很麻烦。
有没有更快的方法来完成此类文本处理任务?
答案1
您可以执行与所描述的完全相同的操作,但无需使用文件或编辑器。只是不要指定文件名作为cat
命令的参数。这意味着cat
将从标准输入读取。然后,在过滤器管道等待的情况下,您只需将文本粘贴到终端,然后按CTRL-D
关闭cat
.
缺点是过滤后的输出与输入文本混合在一起。如果过滤器将输出存储到某个文件中,这并没有什么坏处。
答案2
您的用例不够具体,但如果使用 Bash 不是问题,那么您可以受益于提示命令。
PROMPT_COMMAND='touch ~/.last_command_output; LAST_COMMAND_OUTPUT="$(cat ~/.last_command_output)"; exec >/dev/tty; exec > >(tee ~/.last_command_output)'
从现在开始,您可以使用$LAST_COMMAND_OUTPUT
应包含上一个命令的输出的变量。
幕后发生了什么:
PROMPT_COMMAND
是一个变量,定义 BASH 显示提示之前执行的命令(大多数情况下最后一个命令完成工作)touch ~/.last_command_output;
- 创建文件~/.last_command_output
,以便稍后用于存储目的LAST_COMMAND_OUTPUT="$(cat ~/.last_command_output)"
将前面提到的文件的内容存储在名为的环境变量中,LAST_COMMAND_OUTPUT
因此使用它只是稍后简单的 echo 的问题exec >/dev/tty;
-exec
不带参数用于将当前 shell 的输出重定向到/dev/tty
(当前终端设备),这对于删除终端中上一个命令的旧重定向是必要的(请参阅下一个要点)exec > >(tee ~/.last_command_output)
- 使用以下命令运行tee
(它将 stdin 的内容存储在文件内并将其输出到 stdout)流程替代因此 exec 可以将输出重定向到此文件描述符,就像通过管道将其传输到 tee 一样。
这似乎是一个很好的起点。然后您可能可以向其中添加一些其他功能,例如存储最后 N 个命令的输出或确保多个会话不会覆盖用于存储命令输出的文件。
也有缺点。以这种方式重定向输出会导致某些命令注意到输出不是标准输出,并且与在没有 .txt 文件的情况下在终端中运行相比,您可能会遇到不同的行为PROMPT_COMMAND
。终端中可能只有类似没有颜色的内容,但ls
会在一行中输出它的列表,而不是逐行输出每个条目。最值得注意的是需要用户输入的终端程序的问题,例如vi
.警告输入不是终端并且$LAST_COMMAND_OUTPUT
变量中的输出混乱。
另外,只需简单地禁用此功能即可unset PROMPT_COMMAND
。
答案3
将对现有命令的调用包装在如下函数中:
doit() {
local ret=0
exec 3>&1 # save fd 1 (stdout) in fd 3 to restore later
exec > >(tee output.txt) # redirect stdout of this script to go to tee
your_command "${@:--}" # run whatever command you want
ret="$?" # save that command's exit status
exec 1>&3; 3>&- # restore stdout and close fd 3
return "$ret"
}
然后调用doit
而不是your_command
.这将运行your_command
并将其输出保存在文件中output.txt
以供稍后编辑。显然,为函数和输出文件命名适当的名称。
答案4
正如 @muru 所建议的,我现在使用剪贴板到 shell 工具:xsel
。
当我发现 cli 输出需要进一步修改时,我使用 ctrl+shift+c 选择并将其复制到剪贴板。然后我使用xsel -b
(= xsel --clipboard
) 将其作为标准输入粘贴到其他工具中:
$ xsel -b | grep foo | sed s/bar/baz/
这是一种无需设置即可在任何地方使用的解决方案。