bash - with - create alias linux




Hacer un alias Bash que toma un parámetro? (8)

Solía ​​usar CShell ( csh ), que te permite crear un alias que toma un parámetro. La notación era algo así como

alias junk="mv \\!* ~/.Trash"

En Bash, esto no parece funcionar. Dado que Bash tiene una multitud de características útiles, asumo que esta ha sido implementada pero me pregunto cómo.


TL; DR: haz esto en su lugar

Es mucho más fácil y más legible usar una función que un alias para poner argumentos en medio de un comando.

$ wrap_args() { echo "before [email protected] after"; }
$ wrap_args 1 2 3
before 1 2 3 after

Si sigue leyendo, aprenderá cosas que no necesita saber sobre el procesamiento de argumentos de shell. El conocimiento es peligroso. Simplemente obtenga el resultado que desea, antes de que el lado oscuro controle su destino para siempre.

Aclaración

bash alias de bash aceptan argumentos, pero solo al final :

$ alias speak=echo
$ speak hello world
hello world

Poner argumentos en medio del comando a través de un alias es posible, pero se pone feo.

¡No intentes esto en casa, niños!

Si te gusta eludir las limitaciones y hacer lo que otros dicen que es imposible, aquí está la receta. Pero no me culpes si tu cabello se te raspa y tu cara termina cubierta de hollín al estilo científico loco.

La solución es pasar los argumentos que el alias acepta solo al final a un contenedor que los insertará en el medio y luego ejecutará su comando.

Solución 1

Si realmente estás en contra de usar una función per se, puedes usar:

$ alias wrap_args='f(){ echo before "[email protected]" after;  unset -f f; }; f'
$ wrap_args x y z
before x y z after

Puede reemplazar [email protected] con $1 si solo desea el primer argumento.

Explicación 1

Esto crea una función temporal f , a la que se pasan los argumentos (tenga en cuenta que f se llama al final). unset -f elimina la definición de la función a medida que se ejecuta el alias para que no se quede atrás.

Solucion 2

También puedes usar una subshell:

$ alias wrap_args='sh -c '\''echo before "[email protected]" after'\'' _'

Explicación 2

El alias construye un comando como:

sh -c 'echo before "[email protected]" after' _

Comentarios:

  • El marcador de posición _ es obligatorio, pero podría ser cualquier cosa. Se establece en sh $0 s $0 , y se requiere para que no se consuman los primeros argumentos dados por el usuario. Demostración:

    sh -c 'echo Consumed: "$0" Printing: "[email protected]"' alcohol drunken babble
    Consumed: alcohol Printing: drunken babble
    
  • Se requieren las comillas simples dentro de comillas simples. Aquí hay un ejemplo de que no funciona con comillas dobles:

    $ sh -c "echo Consumed: $0 Printing: [email protected]" alcohol drunken babble
    Consumed: -bash Printing:
    

    Aquí, los valores de $0 y [email protected] del shell interactivo se reemplazan en la cita doble antes de que se pase a sh . Aquí está la prueba:

    echo "Consumed: $0 Printing: [email protected]"
    Consumed: -bash Printing:
    

    Las comillas simples aseguran que estas variables no sean interpretadas por el shell interactivo, y se pasan literalmente a sh -c .

    Podría usar comillas dobles y \[email protected] , pero la mejor práctica es citar sus argumentos (ya que pueden contener espacios), y \"\[email protected]\" ve aún más feo, pero puede ayudarlo a ganar un concurso de ofuscación en el que el cabello al descubierto Es un requisito previo para la entrada.


Al refinar la respuesta anterior, puede obtener una sintaxis de 1 línea como puede para los alias, que es más conveniente para las definiciones ad-hoc en un shell o en archivos .bashrc:

bash$ myfunction() { mv "$1" "$1.bak"; cp "$2" "$1"; }

bash$ myfunction original.conf my.conf

No olvide el punto y coma antes del cierre del corchete derecho. Del mismo modo, para la pregunta real:

csh% alias junk="mv \\!* ~/.Trash"

bash$ junk() { mv "[email protected]" ~/.Trash/; }

O:

bash$ junk() { for item in "[email protected]" ; do echo "Trashing: $item" ; mv "$item" ~/.Trash/; done; }

Bash alias no acepta parámetros directamente. Tendrás que crear una función y alias que.

alias no acepta parámetros, pero una función puede llamarse como un alias. Por ejemplo:

myfunction() {
    #do things with parameters like $1 such as
    mv "$1" "$1.bak"
    cp "$2" "$1"
}


myfunction old.conf new.conf #calls `myfunction`

Por cierto, las funciones Bash definidas en su .bashrc y otros archivos están disponibles como comandos dentro de su shell. Así, por ejemplo, puedes llamar a la función anterior como esta

$ myfunction original.conf my.conf

De hecho, las funciones son casi siempre la respuesta, como ya se ha contribuido y confirmado ampliamente con esta cita de la página del manual: "Para casi todos los propósitos, los alias son reemplazados por las funciones de shell".

Para completar y porque esto puede ser útil (una sintaxis ligeramente más liviana) se podría notar que cuando los parámetros siguen el alias, aún pueden usarse (aunque esto no abordaría el requisito del OP). Esto es probablemente más fácil de demostrar con un ejemplo:

alias ssh_disc='ssh -O stop'

me permite escribir algo como ssh_disc myhost , que se expande como se espera como: ssh -O stop myhost

Esto puede ser útil para comandos que toman argumentos complejos (mi memoria ya no es lo que usa t be ...)


La pregunta simplemente se hace mal. No creas un alias que tome parámetros porque el alias solo agrega un segundo nombre para algo que ya existe. La funcionalidad que desea el OP es el comando de function para crear una nueva función. No es necesario asignar un alias a la función, ya que la función ya tiene un nombre.

Creo que quieres algo como esto:

function trash() { mv "[email protected]" ~/.Trash; }

¡Eso es! Puede usar los parámetros $ 1, $ 2, $ 3, etc., o simplemente rellenarlos con $ @


NB: En caso de que la idea no sea obvia, es una mala idea usar alias para cualquier cosa que no sean alias, la primera es la "función en un alias" y la segunda la "redirección / fuente difícil de leer". Además, hay fallas (que pensé que serían obvias, pero en caso de que estés confundido: no quiero que se usen realmente ... ¡en ningún lado!)

.................................................. .................................................. ............................................

He respondido esto antes, y siempre ha sido así en el pasado:

alias foo='__foo() { unset -f $0; echo "arg1 for foo=$1"; }; __foo()'

lo cual es bueno y bueno, a menos que esté evitando el uso de todas las funciones. en cuyo caso puede aprovechar la gran capacidad de bash para redirigir texto:

alias bar='cat <<< '\''echo arg1 for bar=$1'\'' | source /dev/stdin'

Ambos tienen aproximadamente la misma longitud de dar o tomar unos pocos caracteres.

El kicker real es la diferencia de tiempo, la parte superior es el "método de función" y la parte inferior el método de "fuente de redirección". Para probar esta teoría, el momento habla por sí mismo:

arg1 for foo=FOOVALUE
 real 0m0.011s user 0m0.004s sys 0m0.008s  # <--time spent in foo
 real 0m0.000s user 0m0.000s sys 0m0.000s  # <--time spent in bar
arg1 for bar=BARVALUE
[email protected] /usr/bin# time foo FOOVALUE; time bar BARVALUE
arg1 for foo=FOOVALUE
 real 0m0.010s user 0m0.004s sys 0m0.004s
 real 0m0.000s user 0m0.000s sys 0m0.000s
arg1 for bar=BARVALUE
[email protected] /usr/bin# time foo FOOVALUE; time bar BARVALUE
arg1 for foo=FOOVALUE
 real 0m0.011s user 0m0.000s sys 0m0.012s
 real 0m0.000s user 0m0.000s sys 0m0.000s
arg1 for bar=BARVALUE
[email protected] /usr/bin# time foo FOOVALUE; time bar BARVALUE
arg1 for foo=FOOVALUE
 real 0m0.012s user 0m0.004s sys 0m0.004s
 real 0m0.000s user 0m0.000s sys 0m0.000s
arg1 for bar=BARVALUE
[email protected] /usr/bin# time foo FOOVALUE; time bar BARVALUE
arg1 for foo=FOOVALUE
 real 0m0.010s user 0m0.008s sys 0m0.004s
 real 0m0.000s user 0m0.000s sys 0m0.000s
arg1 for bar=BARVALUE

Esta es la parte inferior de unos 200 resultados, realizados a intervalos aleatorios. Parece que la creación / destrucción de funciones lleva más tiempo que la redirección. Esperemos que esto ayude a los futuros visitantes a esta pregunta (no quería guardármelo para mí).


Si está buscando una forma genérica de aplicar todos los parámetros a una función, no solo uno o dos o alguna otra cantidad codificada, puede hacerlo de esta manera:

#!/usr/bin/env bash

# you would want to `source` this file, maybe in your .bash_profile?
function runjar_fn(){
    java -jar myjar.jar "[email protected]";
}

alias runjar=runjar_fn;

Así que en el ejemplo anterior, paso todos los parámetros de cuando ejecuto runjar al alias.

Por ejemplo, si runjar hi there , terminaría ejecutando java -jar myjar.jar hi there . Si runjar one two three , ejecutaría java -jar myjar.jar one two three .

Me gusta esta solución basada en [email protected] porque funciona con cualquier número de parámetros.


Una solución alternativa es usar el marker , una herramienta que he creado recientemente que le permite "marcar" plantillas de comando y colocar fácilmente el cursor en los marcadores de posición del comando:

Descubrí que la mayoría de las veces, utilizo funciones de shell, por lo que no tengo que escribir los comandos de uso frecuente una y otra vez en la línea de comandos. El problema de usar funciones para este caso de uso es agregar nuevos términos a mi vocabulario de comando y tener que recordar a qué funciones se refieren los parámetros en el comando real. El objetivo del marcador es eliminar esa carga mental.





alias