将 grep 传输到 less,将 grep 命令显示为文件名

将 grep 传输到 less,将 grep 命令显示为文件名

less -M将显示文件名作为提示,如下所示:

      1 asdf
test.txt lines 1-1/1 (END)

为了便于阅读,我喜欢将 grep 连接到 less。我可以让 less 将 grep 命令解释为其提示符的文件名吗?

通常只是:

grep asdf test.txt | less

      1 asdf
lines 1-1/1 (END)

我想要:

grep asdf test.txt | less

      1 asdf
grep asdf test.txt lines 1-1/1 (END)

我知道我可以将这一切包装在一个脚本中并使用参数来执行操作,$0但并不想在这里重新发明轮子。

是否仅通过几个命令行技巧就可以实现这一点?

答案1

less根本不知道管道另一端通过标准输入向其提供数据的东西是什么,除非有人大大复杂化代码以less找到less正在运行的进程组和该进程组中的其他进程,然后谁知道它们是如何组合在一起的(shell 知道这些信息但可能不会提供)。

通过阅读,less(1)你可能会发现-P可以自定义提示的选项

$ echo hi | less -P '?f%f:Standard input'
hi
Standard input

所以理论上如果我们可以Standard input用当前的 shell 管道替换位...让我们看看运行set时是什么...less

$ function less { set > whatisset; command less "$@"; }
$ echo foo | less
foo
$ egrep 'echo|foo' whatisset
$ 

因此,对于 没有什么明显的用途mksh,因为echofoo(相当于grep)不会出现在 shell 环境中的任何地方(对于zsh和 哦哇bash在 Linux 上也是一样的,曾经用设置轰炸环境,但又是同样的故事)。实际上,zsh我们可以使用一个preexec函数来使命令行可用:

$ zsh
% function preexec { shift; SHORT=$1; }
% function less { set > whatisset; command less "$@"; }
% echo foo | less
foo
% grep SHORT whatisset
SHORT='echo foo | less'
% 

所以可以做类似的事情

% less() { =less -P '?f%f:'${SHORT%% | less} "$@"; }
% echo hi|less
hi
echo hi

答案2

我违背了自己的意愿,写了一个小脚本来实现这一点。虽然不太美观,但很实用,而且还不错,因为只有几行代码。我们一直在改进。

#!/bin/bash

# store all args as string
allargs="$*"

# create temp file named as grep command
TMPFILE=$(mktemp -q "$allargs")

# run grep command
$* --color=always > "$TMPFILE" # --color=always with less -r will highlight results in less

# show results file in less
less -Mr "$TMPFILE"

# delete the temp file
rm -f -- "$TMPFILE"

以 身份运行./scriptname grep <opts> <regex> <file(s)>

缺点:如果file是(在当前目录中搜索所有内容),那么它们将被扩展并作为文件名的一部分,这会违背目的,因为它会将命令推离屏幕(非常长的文件名)。除非有办法在?*中水平滚动文件名。less

相关内容