6

首先,让我声明这是一个编程问题(因此不属于超级用户等人),因为我说的是 shell 编程。这几乎可能是一个高尔夫问题,但我一开始没有答案,所以任何帮助将不胜感激:-)

所以,故事是:我喜欢用管道输入东西less--quit-if-one-screen因为它很舒服:less在不必要的时候不会妨碍我。还是这样?当我的提示已经在我的终端窗口底部时,这个选项完全符合我的要求(即less表现得像cat)。但是,当我当前的提示位于窗口顶部时,less首先打印大量空白行以清除屏幕,然后在屏幕底部打印出我的(短)文件,然后它才意识到文本较少比一个屏幕,所以它退出,我得到我的提示。

但是这种行为并不好,因为所有那些无用的空白行。我尝试了不同的选项,或者编写了脚本和别名,我能想到的最好的就是这个(我正在使用 zsh,所以 shell 已经能够复制管道等等):

function catless() {
 cat   \
  >>( bucket -$LINES | cat  ) \
  >>( bucket +$LINES | less )
}

bucket我刚刚编写的另一个脚本在哪里,如果它少于 N 行(使用 -N)或多于 N(使用 +N) ,它将stdin复制到stdout 。我把它贴在这里:http ://snipt.net/Gyom/copy-stdin-to-stdout-or-not-depending-on-length

ls | catless几乎可以工作。但是,出于同步的原因,这里涉及的不同进程无法正确访问终端,并且所有操作都在后台执行(特别是,我less在这里从来没有得到正确的,并且提示返回得太快了)。但也许我走错了路。

所以,总而言之,我想要的是这样一个函数/脚本/我可以输入的任何内容,ls | catless它的行为与输出短于一个屏幕时的行为完全相同,而ls | cat当输出长于屏幕时则如此。lsls | less

有任何想法吗 ?

4

3 回答 3

6

-X标志可能会帮助您(来自less(1)):

  -X or --no-init
         Disables sending the termcap initialization and deinitialization
         strings to the terminal.   This  is  sometimes desirable if the
         deinitialization string does something unnecessary, like
         clearing the screen.

所以,以下应该做你想要的:

export LESS="-E -X"

或者,既然你喜欢 --quit-if-one-screen,你可以改为:

export LESS="-F -X"
于 2009-10-19T20:04:31.873 回答
1

less有一个--clear-screen选项(也可用作-c。您可能需要检查您的 $LESS 环境变量以确保它不包含该选项。我的没有,它的行为完全符合您的要求(而不是您试图克服)。

您可以通过使用来临时禁用 $LESS 变量中设置的选项+。例如:

less -+c shortfile

您还应该确保$TERM设置正确。

如果所有其他方法都失败了,请查看“输入预处理器”部分中的$LESSOPEN预处理器和$LESSCLOSE后处理器功能,man less看看是否会导致您采用另一种方法。

于 2009-10-14T15:57:44.477 回答
1

less 版本 406 的新闻中,我看到“不要在第一页移动到屏幕底部。”。你有哪个版本?我的系统版本是382,打印前移动到屏幕底部(如果只有一个屏幕并-F使用会导致空白行)。

我刚刚安装了 436 版,它似乎可以满足您的要求-FX(将它LESS与您的其他首选项一起放在 env var 中,让任何东西都可以通过运行来使用这些首选项less)。

如果您无法获得新版本,您可以尝试以下方法:

function catless() {
    local line buffer='' num=0 limit=$LINES
    while IFS='' read -r line; do
        buffer="$buffer$line"$'\n'
        line=''
        num=$(( num+1 ))
        [[ $num -ge $limit ]] && break
    done
    if [[ $num -ge $limit ]]; then 
        { printf %s "$buffer$line"; cat } | less
    else
        printf %s "$buffer$line"
    fi
}

关键是 shell 必须在它(可能)启动之前知道文件中的行数是否比屏幕less多(您最初使用的多 io 技术只能在后台运行)。如果 in-shellread对您来说不够健壮,您可以通过修改代码来替换它:

function cat_up_to_N_lines_and_exit_success_if_more() {
    # replace this with some other implmentation
    # if read -r is not robust enough
    local line buffer='' num=0 limit="$1"
    while IFS='' read -r line; do
        buffer="$buffer$line"$'\n'
        line=''
        num=$(( num+1 ))
        [[ $num -ge $limit ]] && break
    done
    printf %s "$buffer$line"
    [[ $num -ge $limit ]]
}
function catless() {
    local limit=$LINES buffer=''
    # capture first $limit lines
    # the \0 business is to guard the trailing newline
    buffer=${"$(
    cat_up_to_N_lines_and_exit_success_if_more $limit
    ec=$?
    printf '\0'
    exit $ec)"%$'\0'}
    use_pager=$?
    if [[ $use_pager -eq 0 ]]; then
        { printf '%s' "$buffer"; cat } | less
    else
        printf '%s' "$buffer"
    fi
}
于 2009-10-31T17:13:29.273 回答