¿Cómo hacer una frase expandible especial en bash?


12

Me encuentro haciendo <command> --help | grep <feature>muy muy a menudo todos los días. Me preguntaba si era posible hacer que algo así se ^^expanda "--help | grep"y luego hago esto:

ls ^^ size

Eso ejecutaría lo siguiente:

ls --help | grep size

Respuestas:


17

Puede usar una función bash para eso:

Ponga lo siguiente en su ~ / .bashrc:

qh() {
    type -all "$1" ; { man "$1" || "$1" --help ;} | egrep -i -- "$2"
}

Cuando guarde su bashrc do source ~/.bashrc, puede hacer:

$ qh ls size
      --block-size=SIZE      scale sizes by SIZE before printing them; e.g.,
                               '--block-size=M' prints sizes in units of
  -h, --human-readable       with -l and/or -s, print human readable sizes
  -s, --size                 print the allocated size of each file, in blocks
  -S                         sort by file size, largest first
      --sort=WORD            sort by WORD instead of name: none (-U), size (-S),
  -T, --tabsize=COLS         assume tab stops at each COLS instead of 8

1
debe cotizar $ 1 y $ 2. Cambiaría esto a: qh () { type -all "$1" ; { "$1" --help || man "$1" ;} | egrep -i -- "$2" ;} # por lo tanto, podría: qh ls size, qh ls "algo | otro" etc. el (opcional) type -all "$1"también agregará la información sobre $ 1: dice si lanzará un alias, una función, un comando, etc. Y da información del hombre "$ 1" si el comando $ 1 no tenía la opción "--help" (esto sucede a veces)
Olivier Dulac

1
@OlivierDulac ¿Puede explicar un poco más sobre el tipo -todos "$ 1"? ¿En qué caso será necesario?
tgwtdt

Mi versión de tipo (kubuntu 16.04) sabe -a, pero no dice nada sobre -lo -all, pero la función funciona.
Joe

15

Con zsh, usarías un alias global :

$ alias -g '^^=--help|grep --color -i'
$ ls ^^ size
     --block-size=SIZE      scale sizes by SIZE before printing them; e.g.,
                              '--block-size=M' prints sizes in units of
                              1,048,576 bytes; see SIZE format below
 -h, --human-readable       with -l and/or -s, print human readable sizes
 -s, --size                 print the allocated size of each file, in blocks
 -S                         sort by file size, largest first
     --sort=WORD            sort by WORD instead of name: none (-U), size (-S),
 -T, --tabsize=COLS         assume tab stops at each COLS instead of 8
The SIZE argument is an integer and optional unit (example: 10K is 10*1024)

Con bash, es posible que pueda usar la expansión de historial, que es una que ocurre lo suficientemente temprano en el análisis de sintaxis de shell que puede funcionar para sustituir una tubería:

  1. Imprima la historia con el texto que desea sustituir y un carácter especial que probablemente no usará de otra manera (como £aquí que está en mi teclado):

     $ --help $(: £)|grep
     bash: --help: command not found
     Usage: grep [OPTION]... PATTERN [FILE]...
     Try 'grep --help' for more information.
  2. Luego, usando la expansión del historial para recuperar eso:

    $ ls !?£? size
    ls --help $(: £)|grep size
         --block-size=SIZE  scale sizes by SIZE before printing them; e.g.,
                              '--block-size=M' prints sizes in units of
     -h, --human-readable   with -l and/or -s, print human readable sizes
     -s, --size             print the allocated size of each file, in blocks
     -S                     sort by file size, largest first
         --sort=WORD        sort by WORD instead of name: none (-U), size (-S),
     -T, --tabsize=COLS     assume tab stops at each COLS instead of 8

O podría haber readlineexpandido --help|grepsobre alguna tecla o secuencia de teclas presionar. Para que eso se aplique bashsolo (y no a otras aplicaciones como gdbusar readline), puede usar el bindcomando bash builtin, que es bashla API de configuración readline, por ejemplo en su ~/.bashrc:

bind '"^^": "--help|grep "'

O agregue a su ~/.inputrc(archivo de configuración de readline):

$if Bash
"^^": "--help|grep "
$endif

(hay otros shells como rco esque usan readline y donde hacer ese enlace podría tener sentido, pero AFAICT, no configuran la rl_readline_namevariable antes de invocar, readlinepor lo que no podrá agregar algunas $ifdeclaraciones para ellos (se mostrarían como othertodas las aplicaciones) que usan readline sin decirle el nombre de su aplicación)).

Tenga en cuenta que debe ingresar el segundo ^dentro de medio segundo (por defecto) después del primero para que ocurra la sustitución.


¿Puedes explicar un poco más la solución readline? ¿Dónde debo agregar ese enlace? ¿Sobre qué aplicaciones se expandirá ese enlace?
yukashima huksay

@yukashimahuksay, ver edición
Stéphane Chazelas

8

Puede usar enlaces de línea de lectura:

agregar una línea como

"^^": "--help | grep "

a su ~ / .inputrc

Luego presione ^ X ^ R en su término, y el enlace se activará.

La incrustación ls ^^ahora dará como resultado ls --help | grep.


Respondí antes de ver que Stephane había agregado la solución readline. Eliminé mi respuesta, pero luego recuperé la vista, cuando vi el comentario preguntando sobre los detalles para la solución de línea de
lectura

2
Ahora he agregado un poco más sobre eso en mi respuesta.
Stéphane Chazelas

1
Respuestas específicas como la suya, y respuestas completas como la de Stéphane, ambas tienen su lugar. Tener un voto a favor!
obispo el

5

Utilizando lesspara ver el mensaje de ayuda

Puede resultarle útil ver el contexto circundante de las líneas que coinciden con su consulta de búsqueda.

hh () { "${1}" --help | less -p "${2}" ; }

La sintaxis para llamar a esta bashfunción es similar a la función qhen la respuesta de @ tgwtdt, siendo el primer argumento el comando a examinar y el segundo argumento el término de búsqueda. Por ejemplo:

hh ls size
hh ls "symbolic link"

Esto abre el mensaje de ayuda completo less, resalta cada instancia del término de búsqueda y se desplaza a la primera instancia del término de búsqueda. Luego puede presionar npara avanzar a la siguiente línea que contiene el término de búsqueda, nnuevamente para la siguiente, y así sucesivamente. Para volver a una instancia anterior, presione N. Utilice los Home, End, Page Up, Page Down, Up Arrow, y Down Arrowteclas para la navegación en general. Presione qo Qpara salir lessy regresar a la línea de comando.


3

Me gustó la solución de @tgwtdt, así que la mejoré un poco.

Esto hace lo mismo, pero hace un poco para manejar los errores y también trata de procesar los elementos integrados.

qh usa () en lugar de {}, entonces qh1 () y out son locales (en una subshell).

function qh () (
    function qh1 () {
      out="$(help "$1" 2>&1 )"
      [ $? -ne 0 ] && return 1
      echo "$out"
    }

    type -all "$1" ; { qh1 "$1" || "$1" --help 2>/dev/null || man "$1" 2>/dev/null ;} | egrep -i -- "$2"
) 
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.