有什么办法交互式 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 退出时随之消失。