Tengo un script bastante simple que es algo como lo siguiente:
#!/bin/bash
VAR1="$1"
MOREF='sudo run command against $VAR1 | grep name | cut -c7-'
echo $MOREF
Cuando ejecuto este script desde la línea de comando y le paso los argumentos, no obtengo ningún resultado. Sin embargo, cuando ejecuto los comandos contenidos dentro de la $MOREF
variable, puedo obtener resultados.
¿Cómo se pueden tomar los resultados de un comando que debe ejecutarse dentro de un script, guardarlo en una variable y luego mostrar esa variable en la pantalla?
bash
shell
command-line
Juan
fuente
fuente
echo
la variable es un uso inútil deecho
, y un uso inútil de variables.Respuestas:
Además de los backticks
`command`
, la sustitución de comandos se puede hacer con$(command)
o"$(command)"
, que me resulta más fácil de leer, y permite anidar.Las comillas (
"
) son importantes para preservar los valores de las variables de varias líneas ; es opcional en el lado derecho de una tarea, ya que no se realiza la división de palabras , porOUTPUT=$(ls -1)
lo que funcionaría bien.fuente
echo
comando.${OUTPUT}foo
. También son necesarios cuando se realizan operaciones de cadena en línea en la variable, como${OUTPUT/foo/bar}
La forma correcta es
Si vas a usar un apóstrofe, es necesario
`
, no'
. Este personaje se llama "backticks" (o "acento grave").Me gusta esto:
fuente
echo
.$()
funciona. No se pudo solucionar hasta que vi esta página.Algunos trucos de Bash que uso para establecer variables a partir de comandos
2nd Edit 2018-02-12: Agregado de una manera diferente, ¡busca en la parte inferior de este para tareas de larga duración !
25-01-2018 Editar: se agregó una función de muestra (para rellenar variables sobre el uso del disco)
Primera forma simple, antigua y compatible
Mayormente compatible, segunda forma
Como la anidación podría volverse pesada, se implementó un paréntesis para esto
Muestra anidada:
Lectura de más de una variable (con Bashisms )
Si solo quiero un valor usado :
podrías ver una variable de matriz :
Entonces:
Pero prefiero esto:
El primero
read foo
simplemente saltará la línea del encabezado, pero en un solo comando, completará 7 variables diferentes :O incluso:
... también funcionará con matrices asociativas :
read foo disk[total] disk[used] ...
Función de muestra para rellenar algunas variables:
Nota:
declare
no se requiere línea, solo para facilitar la lectura.Acerca de
sudo cmd | grep ... | cut ...
(¡Evite inútil
cat
! Así que esto es solo un tenedor menos:Todos los tubos (
|
) implican horquillas. Donde se debe ejecutar otro proceso, acceder al disco, llamadas a bibliotecas, etc.Por lo tanto, usar
sed
para la muestra limitará el subproceso a solo una bifurcación :Y con Bashisms :
Pero para muchas acciones, principalmente en archivos pequeños, Bash podría hacer el trabajo por sí mismo:
o
Yendo más lejos sobre la división de variables ...
Eche un vistazo a mi respuesta a ¿Cómo divido una cadena en un delimitador en Bash?
Alternativa: reducir las horquillas utilizando tareas de fondo de larga duración
2nd Edit 2018-02-12:
Para evitar múltiples horquillas como
o
Esto funciona bien, pero ejecutar muchos tenedores es pesado y lento.
¡Y los comandos como
date
ybc
podrían hacer muchas operaciones, línea por línea !Ver:
Por lo tanto, podríamos utilizar un proceso en segundo plano de larga ejecución para realizar muchos trabajos, sin tener que iniciar una nueva bifurcación para cada solicitud.
Solo necesitamos algunos descriptores de archivo y quince para hacerlo correctamente:
(¡Por supuesto, FD
5
y6
tiene que estar sin usar!) ... A partir de ahí, puede usar este proceso de la siguiente manera:En una función
newConnector
Puede encontrar mi
newConnector
función en GitHub.Com o en mi propio sitio (Nota sobre GitHub: hay dos archivos en mi sitio. La función y la demostración están agrupadas en un solo archivo que puede obtenerse para su uso o simplemente ejecutarse para la demostración).Muestra:
La función le
myBc
permite usar la tarea en segundo plano con una sintaxis simple y para la fecha:A partir de ahí, si desea finalizar uno de los procesos en segundo plano, solo tiene que cerrar su fd :
lo cual no es necesario, porque todos los archivos se cierran cuando finaliza el proceso principal.
fuente
EXISTING_CONTAINER=$(docker ps -a | grep "$(echo $CONTAINER_NAME)")
fue la declaración que estaba buscando.echo
; simplemente quieresgrep "$CONTAINER_NAME"
tput
como tarea de fondo para la reproducción del color en la terminal !kubectl get ns | while read -r line; do echo
$ line | grep Término | cut -d '' -f1; done
imprime para cada$line
una una línea vacía y luegobash: xxxx: command not found
. Sin embargo, esperaría que se imprima soloxxx
Como ya te han indicado, debes usar 'backticks'.
La alternativa propuesta también
$(command)
funciona, y también es más fácil de leer, pero tenga en cuenta que solo es válida con Bash o KornShell (y shells derivados de ellos), por lo que si sus scripts tienen que ser realmente portátiles en varios sistemas Unix, debería preferir La antigua notación de backticks.fuente
$()
es totalmente compatible con POSIX sh, estandarizado hace más de dos décadas./bin/sh
en cuenta que en Solaris 10 todavía no reconoce$(…)
, y AFAIK también es cierto en Solaris 11./bin/sh
esksh93
.$()
en el shell POSIX en HP-UX durante los últimos 10 años.Sé tres formas de hacerlo:
Las funciones son adecuadas para tales tareas: **
Invocarlo diciendo
func
.También otra solución adecuada podría ser eval:
El tercero está usando variables directamente:
Puede obtener el resultado de la tercera solución de una buena manera:
Y también de una manera desagradable:
fuente
"$var"
bueno y$var
desagradable?Solo para ser diferente:
fuente
Al configurar una variable, asegúrese de NO tener espacios antes y / o después del signo = . ¡Literalmente pasé una hora tratando de resolver esto, probando todo tipo de soluciones! Esto no es guay.
Correcto:
Fallará con el error "cosas: no encontrado" o similar
fuente
var=value somecommand
se ejecutasomecommand
convar
en su entorno que tenga el valorvalue
. Por lo tanto,var= somecommand
se exportavar
en el entorno desomecommand
con un valor vacío (cero bytes).Si desea hacerlo con comandos / s multilínea / múltiples, puede hacerlo:
O:
Ejemplo:
Salida:
Con heredoc , puede simplificar las cosas con bastante facilidad al dividir su código de línea única larga en uno de varias líneas. Otro ejemplo:
fuente
bash
dentro de la sustitución de comandos? Ya está creando una subshell mediante la sustitución del comando en sí. Si desea poner varios comandos, simplemente sepárelos por nueva línea o punto y coma.output=$(echo first; echo second; ...)
'bash -c "bash -c \"bash -c ...\""'
, también sería "diferente"; pero no veo el punto de eso.ssh
sudo -s
ejecutar comandos mysql dentro, etc. (en lugar de bash)variable=$(bash -c 'echo "foo"; echo "bar"')
másvariable=$(echo "foo"; echo "bar")
: el documento aquí es solo un mecanismo de citas y realmente no agrega nada excepto otra complicación inútil.ssh -p $port $user@$domain /bin/bash <<EOF
para evitarPseudo-terminal will not be allocated because stdin is not a terminal.
advertenciasNecesitas usar cualquiera
$(command-here)
o
Ejemplo
fuente
$()
Es mucho mejor que los backticks. Ver: ¿Cuál es el beneficio de usar $ () en lugar de backticks en scripts de shell?Esta es otra forma y es bueno usarla con algunos editores de texto que no pueden resaltar correctamente cada código complejo que cree:
fuente
Puedes usar backticks (también conocidos como tumbas decorativas) o
$()
.Me gusta:
Ambos tienen el mismo efecto. Pero OUTPUT = $ (x + 2) es más legible y el último.
fuente
Si el comando que está intentando ejecutar falla, escribiría la salida en la secuencia de error y luego se imprimiría en la consola.
Para evitarlo, debe redirigir la secuencia de error:
fuente
Algunos pueden encontrar esto útil. Valores enteros en sustitución de variables, donde el truco es usar
$(())
corchetes dobles:fuente
for ((...))
bucle parecería una mejor coincidencia para la variable de bucle ) Además, no debe usar mayúsculas para sus variables privadas.ARR=(3 2 4 1);for((N=3,M=3,COUNT=N-1;COUNT < ${#ARR[@]};ARR[COUNT]*=M,COUNT+=N)){ :;}
pero estoy de acuerdo con @tripleee: ¡No entiendo qué hacer esto allí!Aquí hay dos formas más:
Tenga en cuenta que el espacio es muy importante en Bash. Por lo tanto, si desea que se ejecute su comando, úselo tal cual sin introducir más espacios.
El siguiente asigna
harshil
aL
y luego lo imprimeLo siguiente asigna la salida del comando
tr
a L2.tr
está siendo operado en otra variable, L1.fuente
$"..."
probablemente no hace lo que crees que hace . 2. Esto ya se da en la respuesta de Andy Lester.echo ${L1,,}
para minúsculas oecho ${L1^^}
mayúsculas.