canalizar la salida de un comando en menos o en función de la longitud de gato

StackOverflow https://stackoverflow.com/questions/1566528

  •  21-09-2019
  •  | 
  •  

Pregunta

En primer lugar, permítanme decir que este es un programación pregunta (y por lo tanto no pertenece en superusuario et. Al. ) porque estoy hablando programación de shell. Esto casi podría ser una cuestión de golf, pero no tengo una respuesta para empezar, por lo que cualquier ayuda sería muy apreciada: -)

Por lo tanto, la historia es: me gusta las cosas tubería en less con la opción --quit-if-one-screen porque es muy cómodo: no lessdoes en mi camino cuando no es necesario. O lo hace? Cuando mi pronta ya se encuentra en la parte inferior de la ventana de terminal, esta opción hace exactamente lo que quiero (es decir, se comporta como less cat). Sin embargo, cuando mi indicador actual es en la parte superior de la ventana, less primera impresiones de un montón de líneas en blanco a clara la pantalla, a continuación, imprime mi archivo (corto) en la parte inferior de la pantalla, y sólo entonces se da cuenta de que hay menos de texto de una pantalla, de modo que salga y que me deben devolver pronta.

Sin embargo, este comportamiento no es muy grande, porque de todas esas líneas en blanco inútiles. Probé diferentes opciones, o escribió guiones y alias, y lo mejor que podía llegar a sería la siguiente (estoy usando zsh, por lo que la cáscara ya es capaz de duplicar las tuberías y así sucesivamente):

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

Cuando bucket es otro script que acabo de escribir, que copia entrada estándar a stdout si es menos de N líneas (con -N) o más de N (con + NORTE). He publicado aquí: http: // snipt .NET / Gyom / copiar-stdin-a-salida estándar-o-no-dependiendo-on-longitud

Y ls | catless casi-works. Sin embargo, por razones de sincronización, los diferentes procesos que intervienen aquí no tienen acceso a la terminal correcta y todo lo que se ejecuta en segundo plano (en particular, nunca consiguen una correcta less aquí, y el indicador regresa muy pronto). Pero tal vez tomé el camino equivocado.

Así que, para resumir, lo que quiero es una función / script / lo que sea que pueda escribir ls | catless y se comporta exactamente como ls | cat cuando la salida del ls es más corta que una pantalla, y al igual ls | less cuando más tiempo.

¿Alguna idea?

¿Fue útil?

Solución

En las noticias por menos versión 406 , veo “Don' se movió a la parte inferior de la pantalla en la primera página.”. ¿Qué versión tienes? Mi versión del sistema es 382 y se mueve a la parte inferior de la pantalla antes de imprimir (causando líneas en blanco si sólo hay una pantalla completa y -F se utiliza).

Acabo de instalar la versión 436, y parece que hacer lo que quiera cuando se administra -FX (ponerlo en el LESS env var con sus otros prefs a dejar que nada utilizar esas Preferencias con sólo correr less).

Si no puede obtener la nueva versión, puede intentar esto en su lugar:

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
}

La clave es que la cáscara tiene que saber si la hay más líneas en el archivo de la pantalla antes de que (potencialmente) lanza less (la técnica de multi-io que utilizó inicialmente sólo puede manejar las cosas en el fondo). Si el read con cáscara no es lo suficientemente robusta como para usted, se puede reemplazar por volver a trabajar un poco su código:

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
}

Otros consejos

La bandera -X podría ayudarle a cabo (desde menos (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.

Por lo tanto, el siguiente debe hacer lo que quiera:

export LESS="-E -X"

O, ya que te gusta --quit-pantalla si uno, en su lugar podría:

export LESS="-F -X"

less tiene una opción --clear-screen (también disponible como -c. Es posible que desee revisar su MENOS variable de entorno $ para asegurarse de que lo hace no incluir esa opción. Mía no y se comporta exactamente como usted queremos (no como usted está tratando de superar).

Puede desactivar las opciones establecidas en la variable $ MENOS en una base ad hoc mediante el uso de +. Por ejemplo:

less -+c shortfile

También debe asegurarse de que $TERM se ha ajustado correctamente.

Si todo lo demás falla, mira el $LESSOPEN pre-procesador y $LESSCLOSE características post-procesador en la sección "ENTRADA del preprocesador" de man less para ver si eso te lleva a otro enfoque.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top