¿Cuál sería en realidad el objetivo de lograr esto? ¿Por qué puede ser esto interesante / relevante?
vanadio
25
@vanadium somos usuarios de Linux, probar cosas sin sentido nos permite aprender técnicas que luego se pueden aplicar a cosas más complejas, si ninguno de nosotros lo hiciera, seamos honestos, ninguno de nosotros estaría aquí
Darren H
1
@DarrenH Eso es lo que realmente pensé :-)
vanadio
Respuestas:
19
La forma simple (y más eficiente) es a través del bucle for (en una línea, pero aquí se muestra en varias líneas para mayor claridad):
for i in{date,grade};do
apt up${i}done
La forma inteligente es crear un alias ~/.bashrcpara estos dos comandos y olvidarse de volver a escribirlo de nuevo:
alias upgrade=' sudo apt update && sudo apt upgrade'
¿Ves lo que está pasando? Estamos creando una cadena de texto válida para que Shell la ejecute. Ahora todo lo que necesita hacer es usar en evallugar de echo. Pero evalgeneralmente no se recomienda en las secuencias de comandos de shell y este comando es mucho más complicado y no portátil que el bucle for. Variación sobre el tema sin evaluación (y la más corta hasta ahora, pero no eficiente debido a la tubería y múltiples comandos echo, dos apt, sudoy shmucho bifurcación):
$ echo "apt "{update,upgrade}";"|sudo sh
También podemos usar setpara convertir la secuencia deseada en parámetros posicionales y simplemente ejecutar aptcon $1y $2args:
O, alternativamente, use for loop nuevamente, ya que el valor predeterminado es procesar parámetros posicionales si no especifica una secuencia en el for variable (sequence)
El uso setes una técnica muy común que veo entre los profesionales que trabajan mucho con los shells, y por una buena razón: es muy portátil y funcionará /bin/shdonde no hay arrays ni {a,b,c}expansión. Así sería POSIX-ly portátil set update upgrade ; for i; do echo apt $i ;done. Además, esto debería ser eficiente.
Simplemente haga el bucle for en una línea. for i in {date,grade}; do sudo apt up${i}; done
Videonauth
3
Si prefiere mantener sus archivos limpios y ordenados, también puede poner alias ~/.bash_aliases. Este archivo debe ser obtenido automáticamente por ~/.bashrc.
francescop21
2
He actualizado mi respuesta con quizás lo que quieres. Es de una sola línea, pero no creo que lo haga más fácil. Francamente, no tiene sentido hacer esto cuando quieres ejecutar dos comandos (sí, son dos aptcomandos) con diferentes argumentos (actualizar y actualizar), así que todavía diré que el bucle es el camino a seguir
Sergiy Kolodyazhnyy
1
No es necesario expandir la cadena para el encabezado del bucle, solo nombra las iteraciones:for i in date grade; do
rexkogitans
55
Tal alias obviamente debe ser nombrado upgrate.
tubería
14
También puede usar la expansión del historial de bash para obtener partes de la línea de comando actual y modificarla:
Entonces puedes correr repeat 'apt up' {date,grade}. Esto tiene la ventaja de ser reutilizable para comandos totalmente diferentes, aunque no le ahorra ningún tipo de escritura para este.
Ciertamente estoy de acuerdo con algunas de las otras respuestas de que algo como esto probablemente sea más útil:
Respuestas:
La forma simple (y más eficiente) es a través del bucle for (en una línea, pero aquí se muestra en varias líneas para mayor claridad):
La forma inteligente es crear un alias
~/.bashrc
para estos dos comandos y olvidarse de volver a escribirlo de nuevo:La forma elaborada es hacer esto:
¿Ves lo que está pasando? Estamos creando una cadena de texto válida para que Shell la ejecute. Ahora todo lo que necesita hacer es usar en
eval
lugar deecho
. Peroeval
generalmente no se recomienda en las secuencias de comandos de shell y este comando es mucho más complicado y no portátil que el bucle for. Variación sobre el tema sin evaluación (y la más corta hasta ahora, pero no eficiente debido a la tubería y múltiples comandosecho
, dosapt
,sudo
ysh
mucho bifurcación):También podemos usar
set
para convertir la secuencia deseada en parámetros posicionales y simplemente ejecutarapt
con$1
y$2
args:O, alternativamente, use for loop nuevamente, ya que el valor predeterminado es procesar parámetros posicionales si no especifica una secuencia en el
for variable (sequence)
El uso
set
es una técnica muy común que veo entre los profesionales que trabajan mucho con los shells, y por una buena razón: es muy portátil y funcionará/bin/sh
donde no hay arrays ni{a,b,c}
expansión. Así sería POSIX-ly portátilset update upgrade ; for i; do echo apt $i ;done
. Además, esto debería ser eficiente.O podemos ir a la
while
ruta del bucle:Por supuesto, recuerde ejecutarlo sin
echo
que tenga lugar la ejecución real del comandofuente
for i in {date,grade}; do sudo apt up${i}; done
~/.bash_aliases
. Este archivo debe ser obtenido automáticamente por~/.bashrc
.apt
comandos) con diferentes argumentos (actualizar y actualizar), así que todavía diré que el bucle es el camino a seguirfor i in date grade; do
upgrate
.También puede usar la expansión del historial de bash para obtener partes de la línea de comando actual y modificarla:
!#
es la línea actual:s/date/grade
es un modificador que sustituyedate
congrade
fuente
!#:s/dat/grad
en su lugarOtra opción simple usando en
xargs
lugar defor
:Prueba:
Sin embargo, preferiría un alias de shell como Sergiy porque estas formas "simples" no son lo suficientemente simples como para ser realmente útiles.
fuente
printf "%s\n" {date,grade} | xargs -I% -n1 echo apt up%
aunque esto sea un poco más largoprintf '%s'
generalmente es una buena práctica ya que no puede escapar de ella, por ejemplo, con--help
o-e
.printf '%s\0'
sería aún mejor,xargs
tiene una bandera para manejar args terminados nulosCrea una función como esta:
Entonces puedes correr
repeat 'apt up' {date,grade}
. Esto tiene la ventaja de ser reutilizable para comandos totalmente diferentes, aunque no le ahorra ningún tipo de escritura para este.Ciertamente estoy de acuerdo con algunas de las otras respuestas de que algo como esto probablemente sea más útil:
fuente
La respuesta de @ muru me llevó a leer sobre la expansión de la historia y encontré otra variante
^string1^string2^
es equivalente a!!:s/string1/string2/
, que toma el último comando y lo reemplazastring1
constring2
.fuente
Reutilizo la
apt-get up
parte del comando usando la siguiente secuencia de teclas:Up ArrowBackspaceBackspaceBackspaceBackspace
fuente