Cómo extender los alias de bash

¿Cómo crear un alias que realmente extienda otro alias del mismo nombre en Bash?

Por qué:

Solía ​​tener GREP_OPTIONS configurado en .bashrc a algo como esto:

 GREP_OPTIONS="-I --exclude=\*~" 

También tenía una secuencia de commands (digamos, setup-java.sh ) a la que llamaría antes de trabajar en algunos proyectos de Java. Contendría la línea:

 GREP_OPTIONS="$GREP_OPTIONS --exclude-dir=classes" 

Si también uso Sass, entonces llamaría a setup-sass.sh que contiene la línea:

 GREP_OPTIONS="$GREP_OPTIONS --exclude-dir=\*/.sass-cache" 

Pero GREP_OPTIONS quedó obsoleto y aparentemente la solución estándar es crear un alias o algún script …

Bash almacena los valores de los alias en una matriz llamada BASH_ALIASES :

 $ alias foo=bar $ echo ${BASH_ALIASES[foo]} bar 

Con la expansión de parameters podemos get el alias del último set (si existe) o el valor pnetworkingeterminado:

 alias grep="${BASH_ALIASES[grep]:-grep} -I --exclude=\*~" 

Ahora solo hazlo en setup-java.sh :

 alias grep="${BASH_ALIASES[grep]:-grep} -I --exclude=\*~ --exclude-dir=classes" 

… y finalmente en setup-sass.sh :

 alias grep="${BASH_ALIASES[grep]:-grep} -I --exclude=\*~ --exclude-dir=\*/.sass-cache" 

Si se llaman las tres líneas, obtenemos lo que queremos:

 $ echo ${BASH_ALIASES[grep]:-grep} grep -I --exclude=\*~ -I --exclude=\*~ --exclude-dir=classes -I --exclude=\*~ --exclude-dir=\*/.sass-cache 

cadena de aliases si los termina con espacios.

 alias print='printf %s\\n ' hey='"hello, fine fellow" ' print hey 

 hello, fine fellow 

Puede escribir scripts completos de esa manera, si está lo suficientemente loco. De todos modos, si desea extender un alias, simplemente asegúrese de que el alias que desea extender termina en un espacio y conecte otro.

 alias grep='printf "%s " -I --exclude=\*~ ' \ exdir=' --exclude-dir=classes ' \ exsass='--exclude-dir=\*/.sass-cache ' grep exdir exsass exdir exsass 

 -I --exclude=*~ --exclude-dir=classes --exclude-dir=*/.sass-cache --exclude-dir=classes --exclude-dir=*/.sass-cache 

Una function es una mejor opción que un alias extensible aquí.

 grep_options=( ) grep() { exec /usr/bin/grep "${grep_options[@]}" ${GREP_OPTIONS} "$@" } 

De esta forma, tiene dos opciones para agregar opciones al entorno:

  • Enmendar la matriz grep_options ; esto apoya correctamente las opciones con espacios, caracteres glob globales y otros casos de esquina:

     grep_options+=( --exclude-dir=classes --exclude-dir='*/.sass-cache' ) 
  • Use la variable escalar GREP_OPTIONS tradicional, a pesar de sus dificultades (vea BashFAQ # 50 para comprender algunos de estos):

     GREP_OPTIONS+=' --exclude-dir=classes ' 

Dicho esto, si desea que sus opciones se reflejen mediante instancias grep invocadas fuera del shell, ni un alias ni una function funcionarán. En cambio, querrá un script de envoltura colocado antes en su PATH que el command grep real. Por ejemplo:

 # in ~/.bash_profile [[ -e ~/bin ]] && PATH=$HOME/bin:$PATH 

… y, en ~/bin/grep :

 #!/bin/bash # load overrides to grep_options on GREP_OPTIONS from local dotfiles source ~/.bash_profile source ~/.bashrc # ...and use them: exec /usr/bin/grep "${grep_options[@]}" ${GREP_OPTIONS} "$@"