首先,让我指出这是一个编程问题(因此不属于superuser等),因为我在说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的输出短于一个屏幕时,它的行为与ls完全相同,而当它的输出长于一个屏幕时,其行为与ls | less完全相同。

有任何想法吗 ?

最佳答案

news for less version 406中,我看到“不要移动到第一页的屏幕底部。”。您有哪个版本?我的系统版本是382,在打印之前它移到屏幕底部(如果只有一个screenful并且使用-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(最初使用的multi-io技术只能在后台运行内容)之前,必须知道文件中的行是否比屏幕上的行多。如果 shell 内read对您而言不够健壮,则可以通过稍微修改代码来替换它:
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
}

关于shell - 将命令的输出根据长度通过管道传递到更少或猫,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/1566528/

10-16 20:21