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
- 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
- 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=date
almacena la cadena date
en 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 g
se pasa al echo
comando como primer argumento. Si ejecuta "$g"
, esto coloca la cadena date
en 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 jj
se divide en dos palabras separadas por espacios. Así, la palabra ping
termina en la posición de mando y la palabra yahoo.com
es 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 gunzip
en lugar de gzip
)
EDITAR:Sobre alias.
El bash
manual 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_File
como 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.