使用 cli 命令快速过滤文本

使用 cli 命令快速过滤文本

有时,我想使用 cli 工具进一步处理/过滤命令行脚本的输出。我无法重新运行该命令,因为它需要很长时间或者不会再次产生相同的输出。

目前,我将输出粘贴到文本编辑器中的新文件中,保存它,然后使用catcli 将其通过管道传输到 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/

这是一种无需设置即可在任何地方使用的解决方案。

相关内容