在转发到标准输出之前手动选择/取消选择行

Bow*_*owi 17 linux bash zsh grep command-line

有什么方法可以交互式grep,这意味着我有一堆来自某个地方的行,我想通过管道进行进一步处理,并且可以选择手动指定我想要的行?

考虑这个例子:

#Name   Food    Music
Adam    Cake    Rock
Bert    Fruit   Folk
Caesar  Cake    Rock
Doris   Cake    Folk
Emil    Fruit   Rock
Francis Fruit   Folk
Gertrud Cake    Rock
...
Run Code Online (Sandbox Code Playgroud)

我可以使用这个文件并使用类似的行过滤它

cat people.txt | grep -v "^#" | grep "^.*Fruit.*Folk"
Run Code Online (Sandbox Code Playgroud)

...让所有人都受邀参加素食民俗派对。当我进一步自动化时:

cat people.txt | grep -v "^#" | grep "^.*Fruit.*Folk" | ??? | peopleInviterScript
Run Code Online (Sandbox Code Playgroud)

...我想???在管道中添加一些让我可以在发送邀请之前选择/取消选择人员的选项。

在 bash/zsh 中是否已经有这样一个我不知道的工具?

Bow*_*owi 21

虽然我喜欢这种vipe方法,但我发现了一种更酷的方法:fzf

cat people.txt | grep -v "^#" | grep "^.*Fruit.*Folk" | fzf -m | cat
Run Code Online (Sandbox Code Playgroud)

...提供了一个不错的列表,我可以在其中搜索并使用键盘切换项目,并在我完成后完全消失。

  • @wjandrea 我从未使用过 `fzf`,但使用 `cat` 可能是因为 `fzf` 的标准输出是一个管道而不是终端,因此会相应地改变其行为。 (8认同)

use*_*686 18

moreutils has vipe,它只是作为管道的一部分运行您的常规文本编辑器(vi 或其他东西)。您未删除的任何行都将被写回标准输出。(不过,一般情况下,您可以通过重定向到临时文件并编辑该文件来获得相同的结果。)


JoL*_*JoL 5

您也可以为此使用gvim(和vim)。插入gvim /dev/stdin您的管道,并:wq! /dev/stdout在完成编辑后进行编写。

如下调用 gvim 可以让您更自然地编写和关闭ZZ

gvim +'nmap ZZ :wq!<cr> | r /dev/stdin | 1d | file /dev/stdout'
Run Code Online (Sandbox Code Playgroud)

您可以创建别名或函数:

gvimp() {
  gvim +'
    nmap ZZ :wq!<cr>
    r /dev/stdin
    1d
    file /dev/stdout
  '
}
Run Code Online (Sandbox Code Playgroud)

这是我删除第 4-7 行并ZZ在正常模式下完成的示例:

$ seq 1 10 | gvimp | sed -r 's/^|$/=/g'
=1=
=2=
=3=
=8=
=9=
=10=
Run Code Online (Sandbox Code Playgroud)

编辑:常规 vim 有点棘手,因为它使用 stdin 进行键盘输入,使用 stdout 绘制用户界面。但是,您仍然可以通过添加额外的进程来使用它。您将 vim 的 std* 重定向到终端,并使用父进程的 std* 作为数据管道。

gvim +'nmap ZZ :wq!<cr> | r /dev/stdin | 1d | file /dev/stdout'
Run Code Online (Sandbox Code Playgroud)

临时文件是必要的,否则管道输出将与 vim 的用户界面混合,并可能在 vim 退出时随之消失。