Asignar comando a variable sin alias

Asignar comando a variable sin alias

Accidentalmente descubrí que en bash, podemos asignar un comando a una variable sin usar alias.

g=date
$g
Mon Jun 27 13:00:40 MYT 2016

Eso funciona. Aquí hay otro ejemplo:

jj="ping yahoo.com"
$jj
PING yahoo.com (98.138.253.109) 56(84) bytes of data.
64 bytes from ir1.fp.vip.ne1.yahoo.com (98.138.253.109): icmp_seq=1 ttl=41 time=347 ms
64 bytes from ir1.fp.vip.ne1.yahoo.com (98.138.253.109): icmp_seq=2 ttl=41 time=345 ms
64 bytes from ir1.fp.vip.ne1.yahoo.com (98.138.253.109): icmp_seq=3 ttl=41 time=345 ms

Estoy usando esta versión de bash.bash --version GNU bash, version 4.1.2(1)-release (x86_64-redhat-linux-gnu)

he investigadointercambio de pilayabdominales tldp, pero no encontré que pudiéramos hacerlo así. Entonces, ¿se trata de una nueva característica de bash o es algo que se pasa por alto? ¿Se considera estosustitución de comando?

Respuesta1

En uso interactivo, el shell lee líneas de entrada desde el dispositivo terminal. Después de haber ingresado una línea, esanalizadodividiéndose enfichas(palabras y operadores). Luego, las fichas o palabras se expanden o resuelven en un orden específico.

Nota: en general, suele ser mejor consultar la fuente canónica de información, como la documentación del proyecto o las especificaciones de la industria, en lugar de fuentes de segunda mano, como la Guía avanzada de scripting Bash, tutoriales en línea, libros o incluso Stack Exchange :). Estas fuentes de segunda mano son útiles para presentar y explicar conceptos en un lenguaje más sencillo, pero normalmente no pretenden ser completas ni reemplazar la documentación oficial. La información de fuentes de segunda mano también puede estar desactualizada.

En este caso, elEspecificación POSIX para analizar comandos simplesEstablece que

  1. Se ampliarán las palabras que no sean asignaciones variables o redirecciones. Si quedan campos después de su expansión, el primer campo se considerará el nombre del comando y los campos restantes serán los argumentos del comando.

ElSección del manual de Bash sobre expansión de comandos simplestambién afirma que

  1. Las palabras que no son asignaciones de variables o redirecciones se expanden (consulte Expansiones de Shell). Si quedan palabras después de la expansión, la primera palabra se considera el nombre del comando y las palabras restantes son los argumentos.

Respuesta2

Esto no es una sustitución de comandos, esvariablesustitución. No estás asignando un comando a una variable, estás asignando una cadena. El comando se ejecuta cuando usa la variable, no en el momento de la asignación.

g=datealmacena la cadena dateen la variable g. Si luego ejecuta echo "$g", esto imprime el valor de g, es decir date(seguido de una nueva línea), porque el valor de gse pasa al echocomando como primer argumento. Si ejecuta "$g", esto coloca la cadena dateen la primera posición del comando, por lo que es el nombre del comando.

Con $jj, entra en juego un segundo factor. Debido a que la expansión de la variable está fuera de las comillas, la“Operador dividido+glob”se aplica al valor. En este caso, esto significa que el valor de jjse divide en dos palabras separadas por espacios. Así, la palabra pingtermina en la posición de mando y la palabra yahoo.comes el primer argumento.

Respuesta3

Este es el comportamiento esperado y ha estado funcionando durante años. Es útil para crear comandos en scripts.

Digamos, por ejemplo, que a veces debería aplicar descompresión en alguna entrada antes de enviarla a una canalización (y compresión en la salida después), pero a veces no. Usando bash:

if (( use_compression == 1 )); then
   infilter='gzip -d -c'
   outfilter='gzip -c'
else
   infilter='cat'
   outfilter='cat'
fi

$infilter "$indatafile" | somepipeline | $outfilter >"$outdatafile"

¿Es sustitución de mando? No. "Sustitución de comando" se refiere específicamente a la sustitución $(...)o la variante de acento grave con el contenido de su salida.

esto es en cambioexpansión de parámetros, es decir, simplemente reemplazando los parámetros con sus valores. Esto sucede antes de que se ejecute el comando y es por eso que funciona.

Esto significa que cosas como las siguientes también funcionan en la línea de comando:

$ decompress='gzip -d -c'
$ ${decompress/g/gun/} filename >unzippedfilename

(eso se ejecutaría gunzipen lugar de gzip)

EDITAR:Sobre alias.

El bashmanual dice:

Para casi todos los propósitos, los alias son reemplazados por funciones de shell.

... y estoy de acuerdo.

Los alias son buenos para cosas cortas como

alias ls="ls -F"

(Ese es el único alias que tengo en mis propias sesiones de shell)

Probablemente no desee utilizar expansiones de parámetros para comandos de "aliasing" en la línea de comando. Aunque no sea por otra razón que no sea que escribir sea un dolor de cabeza. La expansión de parámetros tampoco permite realizar tareas un poco más complejas, como la canalización.

Si tiene operaciones moderadamente complejas que realiza con regularidad, utilice funciones de shell para ellas.

Tomando el ejemplo de la respuesta aceptada aLa pregunta de U&L(al que enlaza en los comentarios a continuación):

alias my_File='ls -f | grep -v /'

Este alias obviamente funciona, pero usando

my_File='ls -f | grep -v /'

no funcionará si luego intentas usarlo $my_Filecomo comando en la línea de comando (como se explica por qué en ese hilo de U&L).

Con una función de shell, también podrás hacer cosas como pasar argumentos:

function my_File {
    ls -l "$@" | fgrep -v '/'
}

$ my_File -iF symlink
84416642 lrwxr-xr-x  1 kk  staff  4 Jun 27 09:03 symlink@ -> file

Respuesta4

Se trata simplemente de utilizar variables de shell, un concepto que ha existido y funcionado así durante décadas (sin exagerar).

Cuando colocas una variable en una línea de comando, el shell la sustituye y luego ejecuta el comando, por lo que si tu variable está al principio, obviamente se considerará como el comando.

información relacionada