Bash

如何在管道中重新執行第 k 個命令?

  • October 13, 2016

我有以下管道:

➜  echo ,cats,and,dogs, | sed -e 's/,[^,]*,[^,]*,/,,,/'
,,,dogs,

我知道我可以執行一個命令,比如!!“執行最後一個命令”或!:1“獲取最後一個參數”,但我想知道是否有一些可以執行的命令讓我“k從管道”

因此,在此範例中,如果我想將其他一些輸出通過管道傳輸到sed實用程序中,我可以在執行上述管道後立即執行以下操作:

$ echo ,foo,bar,baz, | %:2

%:2我不知道的一些可能是虛構的命令在哪裡,“在管道中執行第k一個命令”這個命令是否存在?

在 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+2``Alt+Shift+P用於最後 2 個管道元素。

(z)呼叫 shell 解析器將命令行拆分為單詞。我們找到我們想要的,然後用一個空格|連接右邊的單詞。這意味著它將成為,但只要您不使用複雜的多行結構(例如不會更改為),那不應該影響命令的含義。|tr a b``| tr a b``sed 's/ /x/'``sed 's/ /x/'

如果您不想定義新的小元件,您可以做的另一件事是向後搜尋(使用Ctrl+R假設emacs模式,儘管您可以在vi模式中執行等效操作)搜尋 previous |,刪除到行尾Ctrl+K並返回您的命令 ( Down) 將其粘貼到Ctrl+Y. 這仍然比使用歷史擴展更快,並且仍然是可視的(您可以更好地直覺地選擇|要從中刪除的內容)。

引用自:https://unix.stackexchange.com/questions/315826