我经常以这种方式将我的终端输出重定向到 vim,我厌倦了一直打字:
ls | vim -
我想定义一个函数v
来为我做这件事,即我希望能够输入:
v ls
并且这以某种方式“扩展”到上一个命令。
我可以使用这种脚本在简单的情况下执行此操作(当然,这可以重构为一个小函数):
#!/bin/bash
touch crrt_cmd
while (( "$#" )); do
echo -n $1 >> crrt_cmd
echo -n " " >> crrt_cmd
shift
done
chmod +x crrt_cmd
bash crrt_cmd | vim -
rm crrt_cmd
这适用于非常简单的命令,例如ls
or ls -l
,但是当某些管道存在时,它根本不起作用。
关于如何执行类似操作的任何想法,但适用于任何有效的 bash 命令?
所以为了清楚起见,如果可能的话,我希望事情以这种方式工作:
v ls | grep keyword | head -5
将转化为:
ls | grep keyword | head -5 | vim -
进程替换可能会提供最接近您想要的语法。
这可行,并且可能符合您的喜好:
这使您可以将整个命令的文本放在一起,并将其放在发送它的命令之后(而不是之前)
vim
,这似乎是您的主要目标。没有-
争论是故意的。您不需要为此定义函数或别名,但当然您可以通过定义为别名或函数
vim
来缩短:v
v
v <(cmd1 | cmd2 | ...)
比 . 多一个字符v 'cmd1 | cmd2 | ...'
。但它也避免了muru 警告的引用地狱。'
,"
, 和\
可以出现在里面<(
)
,它们以通常的方式工作。这也可以很好地嵌套:您可以在命令中使用其他括号,只要它们的使用方式在语法上是正确的。这是过程替换。Bash 创建了一个可以通过类似路径访问的管道
/dev/fd/63
(不要与命令本身所涉及的管道混淆)。它用那个管道的路径代替<(cmd1 | cmd2 | ...)
,所以vim
看到一个像/dev/fd/63
. 您的命令 ,cmd1 | cmd2 | ...
在子 shell 中异步运行,其输出被发送到vim
读取的管道。(这就是为什么你不写-
:vim
从/dev/fd/63
或最终被调用的任何内容中读取,而不是从标准输入中读取。)muru指出,您可以编写一个扩展为的别名
vim <(
:您可以将此别名定义
~/.bash_aliases
放在~/.bashrc
.这让你更接近你最初想要的语法——你只需要
)
在你的命令末尾写一个:进程替换还有一个额外的好处是你可以多次使用它,
<(
)
在同一个命令中编写多个结构,以防你想分别运行多个命令并在单独的vim
缓冲区中查看它们的输出。当然,正如 muru 所说,对于运行管道并在 中打开其输出的用例,后缀操作仍然更简单
vim
,因为您只需要vim
在管道末尾添加另一个命令 for。感谢muru提供的洞察力,
v
可以为vim <(
.最简单的案例:更好的方式来实现你的原始
v
vim <(
)
,上面详述,即使在最简单的情况下也可以使用。但是,当您不编写包含两个或多个命令的管道cmd1 | cmd2
(所以你可能仍然想要一个函数来完成你原来的功能。cmd <infile
FOO=bar cmd
v
您的实现运行一个循环来连接参数的文本。这很复杂,并且在大多数涉及引用的情况下也会中断,即使您修复
$1
以"$1"
防止初始拆分和globbing也是如此。在v 'foo bar'
中,您的v
函数(与任何函数一样)不会收到任何引号:它看到foo bar
. 没关系,因为它作为单个参数接收它......直到它构造一个包含它的脚本并运行该脚本,此时foo bar
被解析为两个单词,这成为两个参数。幸运的是,有一种更可靠的方法,也更简单、更短。
"$@"
扩展为传递给当前函数或当前脚本(如果不在函数中)的所有参数。单独的论点既不会进一步分裂,也不会相互结合。所以你只需要:(当然,如果您要定义
v
做其他事情——也许是vim <(
如上所述的别名——那么您可能会想把它称为其他事情,也许u
。)运行该命令定义了一个 shell 函数
v
,该函数运行在其第一个参数中命名的命令并传递其后续参数。这不会构造一个单独的脚本,也不会使用bash -c
oreval
。所以它不会有错误地拆分或连接参数的风险,因为参数永远不会被拆分或连接:它们是分开进入函数的,并"$@"
单独使用它们。您可以将其放在末尾,
~/.bashrc
以便为您的交互式 shell 定义它。或者,如果您更喜欢它是一个脚本,则使用以下内容创建一个名为
v
(或任何您想要的命令名称)的文件:标记文件可执行文件 (
chmod +x v
) 并将其放在$PATH
. 我建议,如果它存在,它会在您登录时~/bin
自动添加到您的帐户中(除非您已更改为不这样做)。$PATH
~/.profile
函数不能对 bash 中的任意非简单命令执行此操作,因为函数本身就是一个简单命令——当函数定义开始起作用时,为时已晚。别名的扩展可以包含管道,因此您可以在别名中添加 piplines,但当然只能在命令的开头:
如果您要选择将不可避免地遵循以下内容的精神错乱:
你迟早会引用地狱的话。
去后缀操作,它更简单。
精神错乱的其他选择:
zsh 中的全局别名
您可以在 zsh 的命令行中的任何位置(而不仅仅是开头)展开别名: