bash 的 ctrl-x e 可以从标准输入初始化吗?

bash 的 ctrl-x e 可以从标准输入初始化吗?

bash 中有一个我经常使用的功能,按下C-x e将在中打开当前命令提示符$EDITOR,关闭缓冲区时将执行写入的命令。

有一个相关命令,fc它从 bash 历史记录中获取输入。手动的表明它根本不使用标准输入。

我想要一个cmd类似于这样的命令:echo "ls" | cmd打开一个包含的缓冲区ls,并在写入该缓冲区时执行给定的命令(就像上面的任何一个命令一样)。是否有具有此属性的现有命令?

答案1

这个技巧在我的 Debian 9 中有效:

echo "ls" | vipe | . /dev/stdin

vipe允许您在 unix 管道中间运行编辑器并编辑程序之间传输的数据。它来自包moreutils。它尊重EDITOR变量。

至少存在两个问题:

  1. 上面的命令.在子 shell 中起作用。您可以将例如放在foo=bar缓冲区中并执行它,但它不会影响您当前的 shell。即使我们制作cmd(例如,作为 shell 函数).它在 shell 解释中起作用cmd,您仍会像使用它一样使用它echo "ls" | cmd,因此整个cmd不会在您当前的 shell 中起作用。

    如果这个问题对您来说是一个问题,请进行研究shopt -o lastpipeset +m试验它们。

  2. 命令将看到它们的 stdin 来自管道。我的测试表明,.在解释任何内容之前会读取整个文件(在我们的例子中是流)。您要运行的命令不会消耗流的某些部分,因为当它们启动时,管道已被关闭vipe

    在这种情况下.是安全的,但bash实际上并非如此(至少在我的 Debian 9 中 GNU Bash 4.4.12 是安全的)。比较以下两个:

    yes cat | head -n 100 | . /dev/stdin    # cats die silently
    yes cat | head -n 100 | bash            # the first cat catches later cats
    

    因此,.命令不会消耗管道;这很好。但有些命令可能会发现关闭的管道不可接受。例如:

    $ echo "top" | vipe | . /dev/stdin    # change nothing and exit the editor
    top: failed tty get
    

    以下函数尝试解决该问题:

    cmd() { </dev/tty . <(vipe); }
    

    现在如果您调用echo "top" | cmd那么vipe将从管道读取,但是您在缓冲区中接受的命令将用作/dev/tty其标准输入。

    Notevipe本身(将其输入流保存到文件后)操纵其描述符,打开并生成使用( )原始 stdin 和 stdout 的/dev/tty编辑器。仍然不存在同时读取的风险,因为编辑器必须在将任何内容发送到其(原始)stdout 之前退出。该工具是一个 Perl 脚本,请阅读并亲自查看。/dev/ttyvipe/dev/ttyvipe


也许您的用例不一定需要管道。也许您可以放入.当前 shell。示例:

# initial commands taken from a file (template)
. <(</the/file vipe)

# initial commands generated by some program
. <(code_generator | vipe)

# initial commands provided as here document
. <(vipe <<EOF 
ls
foo=baz
EOF
)

这些代码片段不仅会影响当前 shell(例如 set foo),而且不会受到重定向输入的影响(例如top不会出现任何抱怨)。

前两个代码片段可以转换为函数。您可以提供一个路径(分别指向模板或生成器,或者可能是整个 shell 命令)作为参数。基于第一个代码片段的示例函数:

template() { . <(<"$1" vipe); }

现在,您可以使用自定义修改重新获取您的~/.bashrc(严格来说:它的副本)而无需实际修改原始文件。就像这样:

template ~/.bashrc

注意vipe,除非您终止它或编辑器报告错误(即非零退出状态),否则将把临时文件打印到其标准输出。退出编辑器而不保存文件不足以中止;在这种情况下,原始文件将被进一步传输。如果您不想执行任何操作,请从文件中删除每个命令并保存它,这样它在获取源代码时就不会运行任何内容;或者让您的编辑器报告失败(例如:cqvi)。

相关内容