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

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

有什么办法交互式 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
...

我可以获取此文件并使用类似的行对其进行过滤

cat people.txt | grep -v "^#" | grep "^.*Fruit.*Folk"

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

cat people.txt | grep -v "^#" | grep "^.*Fruit.*Folk" | ??? | peopleInviterScript

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

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

答案1

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

cat people.txt | grep -v "^#" | grep "^.*Fruit.*Folk" | fzf -m | cat

...提供了一个很好的列表,我可以在里面搜索并用键盘切换项目,当我完成后它就会完全消失。

答案2

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

答案3

您也可以使用gvim(和vim) 来实现这一点。插入gvim /dev/stdin到您的管道中,并:wq! /dev/stdout在完成编辑后通过执行进行写入。

像下面这样调用 gvim 可以让你更自然地书写和关闭ZZ

gvim +'nmap ZZ :wq!<cr> | r /dev/stdin | 1d | file /dev/stdout'

您可以创建它的别名或函数:

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

ZZ下面是一个示例,我删除了第 4-7 行并以正常模式完成:

$ seq 1 10 | gvimp | sed -r 's/^|$/=/g'
=1=
=2=
=3=
=8=
=9=
=10=

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

vimp() {
  bash -c '
    terminal="/dev/$(ps -o tty= $$)"
    tmp_out="$(mktemp)"
    trap "rm \$tmp_out" EXIT
    vim <(cat) < "$terminal" &> "$terminal" +"
      file $tmp_out
      set noreadonly
      nmap ZZ :wq!<cr>
    "
    cat "$tmp_out"
  '
}

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

相关内容