bash 在最后一个屏幕上打开 `less` 的一行 w/o 临时文件

bash one-liner for opening `less` on the last screen w/o temporary files

我尝试在来自标准输入的多屏幕输出的最后一个屏幕上创建一个用于打开 less 的单行代码。这样做的原因是我正在开发一个生成长 AST 的程序,我需要能够上下遍历它,但我更愿意从底部开始。我想到了这个:

$ python a.py 2>&1 | tee >(lines=+$(( $(wc -l) - $LINES))) | less +$lines

首先,我需要计算输出中的行数并从中减去 $LINES,这样我就知道最后一个屏幕的最上面的行是什么。稍后我将需要重用 a.py 输出,因此我将 tee 与进程替换一起用于该目的。作为最后一步,我指向 less 在特定行上打开原始标准输出。当然,它在 Bash 中不起作用,因为在最后一步中未设置 $lines,因为每个子命令在子 shell 中都是 运行。在 ZSH 中,即使子 shell 中没有管道命令 运行,进程替换仍然存在,因此它也不起作用。这不是家庭作业或工作任务,我只是想知道是否可以在不在 BashZSH 中创建临时文件的情况下做我想做的事情。有什么想法吗?

less天生支持这一点。您正在使用的 + 语法接受您在 运行 时可以输入的任何更少的命令,包括 G for go-to-end.

... | less +G

完全符合您的要求。

这实际上是mentioned explicitly as an example in the man page(搜索“+G”)。

您问题的真正答案应该是 +Gless 选项,但您表示问题定义不能代表您要解决的抽象问题。因此,请考虑这个备选问题:

python a.py 2>&1 | \
awk '
  {a[NR]=[=10=]}
  END{
    print NR
    for (i=1;i<=NR;i++)print a[i]
   }
 ' | {
     read -r l
     less -j-1 +$l
 }

awk 命令正在打印行数,然后按顺序打印所有行。我们定义第一行包含一些元信息。这将通过管道传输到一组由 {} 分隔的命令。第一行由 read 使用,存储在变量 $l 中。剩下的几行取less,这里就可以用到这个变量了。使用 -j-1,所以匹配的行在屏幕的底部。