¿Es posible usar variables de parámetros de shell ($ 1, ..., $ @) directamente en la CLI?

9

A veces es necesario emular y verificar las variables anteriores en pequeños ejemplos y luego se puede copiar de inmediato a algún script, etc.

Traté de resolver usando un ejemplo simple de las siguientes maneras:

(find $1) /tmp
sh -c '(find $1) /tmp'
sh -c "find $1" /tmp
echo '(find $1) /tmp' | sh

y con otras combinaciones. También experimentó agregando la directiva del intérprete shebang #!/bin/sh -x, pero no obtuvo el resultado deseado.

¿Puedo hacer esto simplemente?

Apóstol
fuente
1
(find $1) /tmpes un error de sintaxis En realidad (any-command) more-argumentses un error de sintaxis. ¿Puedes explicar de manera diferente lo que estás tratando de hacer?
Celada
2
@Celada, no es un error de sintaxis en los depósitos de la rcfamilia ( rc, es, akanga...), donde en ese caso que es equivalente a find $1 /tmp.
Stéphane Chazelas

Respuestas:

15

El primer argumento después sh -c inline-scriptva a $0(que también se usa para mensajes de error), y el resto entra $1, $2...

$ sh -c 'blah; echo "$0"; echo "$1"' my-inline-script arg
my-inline-script: blah: command not found
my-inline-script
arg

Entonces quieres:

sh -c 'find "$1"' sh /tmp

(en los viejos tiempos, podías encontrar shimplementaciones donde entró el primer argumento $1, así que harías:

sh -c 'find "$1"' /tmp /tmp

O:

sh -c 'shift "$2"; find "$@"' sh 3 2 /tmp1 /tmp2

para tener en cuenta ambos comportamientos, pero esos depósitos han desaparecido ahora que POSIX es frecuente y está disponible públicamente).


Si desea establecer $1, $2en un ámbito local dentro del shell actual, allí es donde usaría las funciones. En conchas tipo Bourne:

my_func() {
  find "$1"
}
my_func /tmp

Algunos shells admiten funciones anónimas. Ese es el caso de zsh:

(){find "$1"} /tmp

O es:

@{find $1} /tmp

Para cambiar los parámetros posicionales actuales, de forma permanente, la sintaxis depende del shell. dchirikov ya ha cubierto el Bourne como conchas (Bourne, Korn bash, zsh, POSIX, ash, yash...).

La sintaxis es:

set arg1 arg2 ... argn

Sin embargo, necesitas:

set --

Para vaciar esa lista (o shift "$#") y

set -- -foo

establecer $1algo que comience con -o +, por lo que es un buen hábito usar siempre set --especialmente cuando se usan datos arbitrarios, como set -- "$@" other-argagregar argumentos al final de la lista de parámetros posicionales.

En shells de la cshfamilia ( csh, tcsh), asigna a la argvmatriz:

set argv=(arg1 arg2)

En los depósitos de la rcfamilia ( rc, es, akanga), a la *matriz:

*=(arg1 arg2)

Aunque también puede asignar elementos individualmente:

2=arg2

En fish, los parámetros posicionales están en la argvmatriz solamente (sin $1, $@allí):

set argv arg1 arg2

En zsh, por compatibilidad con csh, también puede asignar a la argvmatriz:

argv=(arg1 arg2)
argv[4]=arg4

Y también puedes hacer:

5=arg5

Eso significa que también puedes hacer cosas como:

argv+=(another-arg)

para agregar un argumento al final, y:

argv[-1]=()
argv[2]=()

para eliminar un argumento del final o del medio, lo que no puede hacer fácilmente con otros shells.

Stéphane Chazelas
fuente
7
set --

es lo que necesitas:

$ set -- aaa bbb ccc
$ echo "$1"
aaa
$ echo "$2"
bbb
$ echo "$3"
ccc
$ echo "$@"
aaa bbb ccc
dchirikov
fuente