variable una sirve script resultado que programas programacion pasar parametros para manejo guardar español ejemplos cómo comandos comando cadenas bash shell command-line

sirve - ¿Cómo establecer una variable a la salida de un comando en Bash?



programacion shell linux ejemplos (13)

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 comandos y le paso los argumentos, no obtengo ningún resultado. Sin embargo, cuando ejecuto los comandos contenidos en la variable $MOREF , puedo obtener salida.

Me gustaría saber cómo se pueden tomar los resultados de un comando que debe ejecutarse dentro de un script, guardarlo en una variable y luego generar esa variable en la pantalla.


Algunos trucos de bash que utilizo para establecer variables a partir de comandos

2ª Edición 2018-02-12: Agregando una forma especial, ¡vea al final de esto!

2018-01-25 Edición: agregar una función de ejemplo (para poblar vars sobre el uso del disco)

Primera forma antigua y compatible simple.

myPi=`echo ''4*a(1)'' | bc -l` echo $myPi 3.14159265358979323844

Mayormente compatible, segunda vía.

Como la anidación podría volverse pesada, se implementó un paréntesis para esto.

myPi=$(bc -l <<<''4*a(1)'')

Muestra anidada:

SysStarted=$(date -d "$(ps ho lstart 1)" +%s) echo $SysStarted 1480656334

Leer más de una variable (con bashismos ).

df -k / Filesystem 1K-blocks Used Available Use% Mounted on /dev/dm-0 999320 529020 401488 57% /

Si solo quiero valor usado :

array=($(df -k /))

usted podría ver la variable de matriz :

declare -p array declare -a array=''([0]="Filesystem" [1]="1K-blocks" [2]="Used" [3]="Available" [ 4]="Use%" [5]="Mounted" [6]="on" [7]="/dev/dm-0" [8]="999320" [9]="529020" [10]= "401488" [11]="57%" [12]="/")''

Entonces:

echo ${array[9]} 529020

Pero prefiero esto:

{ read foo ; read filesystem size used avail prct mountpoint ; } < <(df -k /) echo $used 529020

La primera read foo solo saltará la línea del encabezado (la variable $foo contendrá algo así como el Filesystem 1K-blocks Used Available Use% Mounted on )

Función de ejemplo para poblar algunas variables:

#!/bin/bash declare free=0 total=0 used=0 getDiskStat() { local foo { read foo read foo total used free foo } < <( df -k ${1:-/} ) } getDiskStat $1 echo $total $used $free

Nota: no se requiere declare línea, solo para facilitar la lectura.

Sobre sudo cmd | grep ... | cut ... sudo cmd | grep ... | cut ...

shell=$(cat /etc/passwd | grep $USER | cut -d : -f 7) echo $shell /bin/bash

(¡Por favor, evite el cat inútil! Así que esto es solo 1 horquilla menos:

shell=$(grep $USER </etc/passwd | cut -d : -f 7)

Todos los tubos ( | ) implican horquillas. Donde se debe ejecutar otro proceso, acceder al disco, llamar a bibliotecas, etc.

Por lo tanto, utilizar sed para la muestra, limitará el subproceso a una sola bifurcación :

shell=$(sed </etc/passwd "s/^$USER:.*://p;d") echo $shell

Y con los bashismos :

Pero para muchas acciones, principalmente en archivos pequeños, bash podría hacer el trabajo por sí mismo:

while IFS=: read -a line ; do [ "$line" = "$USER" ] && shell=${line[6]} done </etc/passwd echo $shell /bin/bash

o

while IFS=: read loginname encpass uid gid fullname home shell;do [ "$loginname" = "$USER" ] && break done </etc/passwd echo $shell $loginname ...

Yendo más allá 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 larga duración en segundo plano

2nd Edit 2018-02-12: para evitar múltiples bifurcaciones como

myPi=$(bc -l <<<''4*a(1)'' myRay=12 myCirc=$(bc -l <<<" 2 * $myPi * $myRay ")

o

myStarted=$(date -d "$(ps ho lstart 1)" +%s) mySessStart=$(date -d "$(ps ho lstart $$)" +%s)

Y porque date y bc podrían trabajar línea por línea :

bc -l <<<$''3*4/n5*6'' 12 30 date -f - +%s < <(ps ho lstart 1 $$) 1516030449 1517853288

Podríamos utilizar un proceso en segundo plano de larga ejecución para realizar trabajos de forma repetitiva, sin tener que iniciar una nueva bifurcación para cada solicitud:

mkfifo /tmp/myFifoForBc exec 5> >(bc -l >/tmp/myFifoForBc) exec 6</tmp/myFifoForBc rm /tmp/myFifoForBc

(¡Por supuesto, FD 5 y 6 deben estar sin uso!) ... A partir de ahí, puede usar este proceso de la siguiente manera:

echo "3*4" >&5 read -u 6 foo echo $foo 12 echo >&5 "pi=4*a(1)" echo >&5 "2*pi*12" read -u 6 foo echo $foo 75.39822368615503772256

En una función newConnector

Puede encontrar mi función newConnector en GitHub.Com o en mi propio sitio (Nota en github, hay dos archivos, en mi sitio, la función y la demo están agrupadas en 1 archivo que puede obtenerse para su uso o simplemente ejecutar la demo)

Muestra:

. shell_connector.sh tty /dev/pts/20 ps --tty pts/20 fw PID TTY STAT TIME COMMAND 29019 pts/20 Ss 0:00 bash 30745 pts/20 R+ 0:00 /_ ps --tty pts/20 fw newConnector /usr/bin/bc "-l" ''3*4'' 12 ps --tty pts/20 fw PID TTY STAT TIME COMMAND 29019 pts/20 Ss 0:00 bash 30944 pts/20 S 0:00 /_ /usr/bin/bc -l 30952 pts/20 R+ 0:00 /_ ps --tty pts/20 fw declare -p PI bash: declare: PI: not found myBc ''4*a(1)'' PI declare -p PI declare -- PI="3.14159265358979323844"

La función myBc permite usar la tarea en segundo plano con una sintaxis simple, y para la fecha:

newConnector /bin/date ''-f - +%s'' @0 0 myDate ''2000-01-01'' 946681200 myDate "$(ps ho lstart 1)" boottime myDate now now ; read utm idl </proc/uptime myBc "$now-$boottime" uptime printf "%s/n" ${utm%%.*} $uptime 42134906 42134906 ps --tty pts/20 fw PID TTY STAT TIME COMMAND 29019 pts/20 Ss 0:00 bash 30944 pts/20 S 0:00 /_ /usr/bin/bc -l 32615 pts/20 S 0:00 /_ /bin/date -f - +%s 3162 pts/20 R+ 0:00 /_ ps --tty pts/20 fw

A partir de ahí, si desea finalizar uno de los procesos en segundo plano, solo tiene que cerrar su fd :

eval "exec $DATEOUT>&-" eval "exec $DATEIN>&-" ps --tty pts/20 fw PID TTY STAT TIME COMMAND 4936 pts/20 Ss 0:00 bash 5256 pts/20 S 0:00 /_ /usr/bin/bc -l 6358 pts/20 R+ 0:00 /_ ps --tty pts/20 fw

que no es necesario, porque todos los fd se cierran cuando finaliza el proceso principal.


Además de backticks ( `command` ), puedes usar $(command) , que me parece más fácil de leer y me permite anidar.

OUTPUT="$(ls -1)" echo "${OUTPUT}"

La cotización ( " ) es importante para preservar los valores de multilínea.


Al establecer una variable, asegúrese de que NO haya 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:

WTFF=`echo "stuff"` echo "Example: $WTFF"

Fallará con error: (cosas: no se encuentra o similar)

WTFF= `echo "stuff"` echo "Example: $WTFF"


Algunos pueden encontrar esto útil. Valores enteros en la sustitución de variables, donde el truco usa $(()) paréntesis dobles:

N=3 M=3 COUNT=$N-1 ARR[0]=3 ARR[1]=2 ARR[2]=4 ARR[3]=1 while (( COUNT < ${#ARR[@]} )) do ARR[$COUNT]=$((ARR[COUNT]*M)) (( COUNT=$COUNT+$N )) done


Aquí hay dos formas más:

Por favor, tenga en cuenta que el espacio es muy importante en bash . Por lo tanto, si desea que su comando se ejecute, úselo tal cual sin introducir más espacios.

  1. A continuación se asigna Harshil a L y luego se imprime.

    L=$"harshil" echo "$L"

  2. A continuación se asigna la salida del comando tr a L2. tr está siendo operado en otra variable L1.

    L2=$(echo "$L1" | tr [:upper:] [:lower:])


Como ya te han indicado, debes usar ''backticks''.

La alternativa propuesta $(command) funciona, y también es más fácil de leer, pero tenga en cuenta que solo es válida con shells bash o korn (y shells derivados de ellos), así que si sus scripts tienen que ser realmente portátiles en varios Unix En sistemas, deberías preferir la notación de backticks anterior.


Conozco tres formas de hacer:

1) Las funciones son adecuadas para tales tareas:

func (){ ls -l }

Invocalo diciendo func

2) También otra solución adecuada podría ser eval:

var="ls -l" eval $var

3) El tercero está usando variables directamente:

var=$(ls -l) OR var=`ls -l`

Usted puede obtener la salida de la tercera solución de buena manera:

echo "$var"

y también de manera desagradable:

echo $var


Esta es otra forma, buena para usar con algunos editores de texto que no pueden resaltar correctamente cada código intrincado que creas.

read -r -d '''' str < <(cat somefile.txt) echo "${#str}" echo "$str"


Necesitas usar cualquiera

$(command-here)

o

`command-here`

ejemplo

#!/bin/bash VAR1="$1" VAR2="$2" MOREF="$(sudo run command against "$VAR1" | grep name | cut -c7-)" echo "$MOREF"


Puede usar garrapatas (también conocidas como tumbas de acento) o $() . Como-

OUTPUT=$(x+2); OUTPUT=`x+2`;

Ambos tienen el mismo efecto. Pero OUTPUT = $ (x + 2) es más legible y el más reciente.


Si desea hacerlo con multiline / multiple command / s, entonces puede hacer esto:

output=$( bash <<EOF #multiline/multiple command/s EOF )

O:

output=$( #multiline/multiple command/s )

Ejemplo:

#!/bin/bash output="$( bash <<EOF echo first echo second echo third EOF )" echo "$output"

Salida:

first second third

Usando heredoc , puede simplificar las cosas bastante fácilmente dividiendo su código de una sola línea larga en uno multilínea. Otro ejemplo:

output="$( ssh -p $port $user@$domain <<EOF #breakdown your long ssh command into multiline here. EOF )"


Solo para ser diferente:

MOREF=$(sudo run command against $VAR1 | grep name | cut -c7-)


Actualización (2018): el camino correcto es

$(sudo run command)

Estás usando el tipo equivocado de apóstrofe. Necesitas ` , no '' . Este personaje se llama "comillas invertidas" (o "acento grave").

Me gusta esto:

#!/bin/bash VAR1="$1" VAR2="$2" MOREF=`sudo run command against "$VAR1" | grep name | cut -c7-` echo "$MOREF"