La decisión es tuya. Si no cita $@
ninguno de sus valores, se someterá a una expansión e interpretación adicionales. Si lo cita, todos los argumentos pasados la función se reproducen literalmente en su expansión. Nunca podrá manejar de manera confiable tokens de sintaxis de shell como, &>|
etc. de cualquier manera sin analizar los argumentos usted mismo de todos modos, por lo que le quedan las opciones más razonables de administrar su función:
- Exactamente las palabras utilizadas en la ejecución de un solo comando simple con
"$@"
.
...o...
- Una versión más amplia e interpretada de sus argumentos que solo se aplican juntos como un comando simple con
$@
.
De ninguna manera está mal si es intencional y si los efectos de lo que eliges se comprenden bien. Ambas formas tienen ventajas una sobre la otra, aunque las ventajas de la segunda rara vez son particularmente útiles. Todavía...
(run_this(){ $@; }; IFS=@ run_this 'ls@-dl@/tmp')
drwxrwxrwt 22 root root 660 Dec 28 19:58 /tmp
... no es inútil , rara vez es muy útil . Y en un bash
shell, porque bash
por defecto no adhiere una definición variable a su entorno, incluso cuando dicha definición se antepone a la línea de comando de una función incorporada especial o a una función, el valor global de $IFS
no se ve afectado y su declaración es local solo a la run_this()
llamada.
Similar:
(run_this(){ $@; }; set -f; run_this ls -l \*)
ls: cannot access *: No such file or directory
... el globbing también es configurable. Las citas tienen un propósito: no son para nada. Sin ellos, la expansión de shell experimenta una interpretación adicional: interpretación configurable . Solía ser, con algunos shells muy antiguos , que $IFS
se aplicaba globalmente a todas las entradas, y no solo a las expansiones. De hecho, dichos shells se comportaron de la misma manera run_this()
que rompieron todas las palabras de entrada sobre el valor de $IFS
. Entonces, si lo que estás buscando es ese comportamiento de shell muy antiguo, entonces deberías usarlo run_this()
.
No lo estoy buscando, y en este momento me cuesta bastante encontrar un ejemplo útil para ello. Generalmente prefiero que los comandos que ejecuta mi shell sean los que escribo en él. Y así, dada la opción, casi siempre lo haría run_that()
. Excepto eso...
(run_that(){ "$@"; }; IFS=l run_that 'ls' '-ld' '/tmp')
drwxrwxrwt 22 root root 660 Dec 28 19:58 /tmp
Se puede citar casi cualquier cosa. Los comandos se ejecutarán entre comillas. Funciona porque para cuando el comando se ejecuta realmente, todas las palabras de entrada ya se han eliminado entre comillas , que es la última etapa del proceso de interpretación de entrada del shell. Entonces, la diferencia entre 'ls'
y ls
solo puede importar mientras el shell está interpretando, y es por eso que las citas ls
aseguran que cualquier alias nombrado ls
no sea sustituido por mi ls
palabra de comando citada . Aparte de eso, las únicas cosas que afectan las citas son la delimitación de palabras (que es cómo y por qué funciona la cita variable / input-whitespace) , y la interpretación de metacaracteres y palabras reservadas.
Entonces:
'for' f in ...
do :
done
bash: for: command not found
bash: do: unexpected token 'do'
bash: do: unexpected token 'done'
Nunca vas a ser capaz de hacer eso con cualquiera de run_this()
o run_that()
.
Pero los nombres de funciones, o $PATH
los comandos 'd', o los builtins se ejecutarán entre comillas o sin comillas, y eso es exactamente cómo run_this()
y cómo run_that()
funcionan en primer lugar. No podrás hacer nada útil con $<>|&(){}
ninguno de esos. Corto de eval
, es.
(run_that(){ "$@"; }; run_that eval printf '"%s\n"' '"$@"')
eval
printf
"%s\n"
"$@"
Pero sin él, estás limitado a los límites de un comando simple en virtud de las comillas que utilizas (incluso cuando no lo haces porque $@
actúa como una comilla al comienzo del proceso cuando el comando se analiza para metacaracteres) . La misma restricción se aplica a las asignaciones y redirecciones de la línea de comandos, que se limitan a la línea de comandos de la función. Pero eso no es gran cosa:
(run_that(){ "$@";}; echo hey | run_that cat)
hey
Podría tener una <
entrada o >
salida tan fácilmente redirigida allí como si abriera la tubería.
De todos modos, en una forma circular, no hay una forma correcta o incorrecta aquí: cada forma tiene sus usos. Es solo que deberías escribirlo mientras piensas usarlo, y debes saber lo que quieres hacer. Omitiendo las cotizaciones pueden tener un propósito - de lo contrario no habría ser cotizaciones en absoluto - pero si los omite por razones no relacionadas con su propósito, estas a escribir código malo. Haz lo que quieres decir; Intento de todos modos.
run_that
El comportamiento es definitivamente lo que esperaría (¿y si hay un espacio en el camino hacia el comando?). Si quisiera el otro comportamiento, ¿seguramente lo citaría en el sitio de la llamada donde sabe cuáles son los datos? Esperaría llamar a esta función comorun_that ls -l
, que funciona igual en cualquier versión. ¿Hay un caso que te hizo esperar de manera diferente?