我有以下管道:
➜ echo ,cats,and,dogs, | sed -e 's/,[^,]*,[^,]*,/,,,/'
,,,dogs,
我知道我可以运行诸如!!
“运行最后一个命令”或!:1
“获取最后一个参数”之类的命令,但我想知道是否有一些我可以运行的命令可以让我“k
从管道”
因此,在这个示例中,如果我想将一些其他输出通过管道传输到sed
实用程序中,我可以在运行上述管道后立即执行类似的操作:
$ echo ,foo,bar,baz, | %:2
哪里%:2
有一些我不知道的可能虚构的命令,“k
在管道中运行第一个命令”这个命令是否存在?
答案1
历史扩展在 80 年代(由 引入csh
)非常巨大,当时终端非常缓慢且有限。但问题是它们不是所见即所得。你看不到它扩展成什么,直到为时已晚(命令已经启动)(尽管有些 shell 允许在按 Enter 键之前执行扩展)。
在这里,我将创建一个小部件,用于在光标处插入最后一个管道元素。与zsh
(将其添加到~/.zshrc
):
last-pipe-elements() {
emulate -L zsh
if [[ $WIDGET = $LASTWIDGET ]]; then
# Invoking the widget several times retrieves pipeline
# elements for older command lines
((last_pipe_elements_iteration++))
LBUFFER=$last_pipe_elements_saved_LBUFFER
else
last_pipe_elements_iteration=1
fi
last_pipe_elements_saved_LBUFFER=$LBUFFER
local -a words
words=(${(z)${history[@]}[last_pipe_elements_iteration]})
local nth_pipe=${words[(In:NUMERIC:)\|]}
((nth_pipe)) || return
LBUFFER+=${(j: :)words[nth_pipe,-1]}
}
zle -N last-pipe-elements
bindkey '\eP' last-pipe-elements
这样,您输入Alt+Shift+P(这里假设发送 ESC 和P
字符序列,您可能需要根据终端进行调整,终端可能会发送\xd0
($'\MP'
)甚至\xf0
($'\Mp')或完全不同的东西,请使用检查Ctrl+V)以插入最后一个命令的最后一个管道元素(包括|
),再次按下它以执行之前的命令,并用于Alt+2Alt+Shift+P最后 2 个管道元素。
(z)
调用 shell 解析器将命令行拆分为单词。我们找到|
我们想要的,然后将其右侧的单词与一空间。这意味着它将|tr a b
成为| tr a b
,但只要您不使用复杂的多行结构(例如sed 's/ /x/'
不会更改为),就不应该影响命令的含义。sed 's/ /x/'
如果您不想定义新的小部件,您可以做的另一件事是向后搜索(使用Ctrl+R假设模式,尽管您可以在模式emacs
中执行等效操作) ,删除到行尾并返回到您的命令 ( ) 将其粘贴到.这仍然比使用历史扩展更快,并且仍然是可视的(您可以更好地直观地选择要从中剪切的内容)。vi
|Ctrl+KDownCtrl+Y|
答案2
不知道如何“在管道之后”,但“在第三个空格之后”可能会有所帮助:
$ echo ,cats,and,dogs, | sed -e 's/,[^,]*,[^,]*,/,,,/'
,,,dogs,
$ echo ,cat,and,mouse, | !:3-$
,,,mouse,
“管道后”的解决方法:
$ echo ,cats,and,dogs, | sed -e 's/,[^,]*,[^,]*,/,,,/'
,,,dogs,
$ after_pipe="$(cut -d "|" -f 2- <<<"!!" )"
$ echo ,cat,and,mouse, | eval "$after_pipe"
$ ,,,mouse,
(cut
如果第一个命令中有带引号的管道“|”,则需要更好的东西。)