{"id":108192,"date":"2022-08-20T03:39:52","date_gmt":"2022-08-20T03:39:52","guid":{"rendered":"https:\/\/magazineoffice.com\/como-usar-eval-en-linux-bash-scripts\/"},"modified":"2022-08-20T03:39:53","modified_gmt":"2022-08-20T03:39:53","slug":"como-usar-eval-en-linux-bash-scripts","status":"publish","type":"post","link":"https:\/\/magazineoffice.com\/como-usar-eval-en-linux-bash-scripts\/","title":{"rendered":"C\u00f3mo usar eval en Linux Bash Scripts"},"content":{"rendered":"


\n<\/p>\n

\n
fatmawati achmad zaenuri\/Shutterstock.com<\/span><\/figcaption><\/figure>\n

De todos los comandos de Bash, pobre viejo eval<\/code> probablemente tiene la peor reputaci\u00f3n. \u00bfJustificado o simplemente mala prensa? Discutimos el uso y los peligros de este menos querido de los comandos de Linux.<\/p>\n

Necesitamos hablar sobre la evaluaci\u00f3n<\/h2>\n

Usado sin cuidado, eval<\/code> puede conducir a un comportamiento impredecible e incluso a inseguridades en el sistema. Por lo que parece, probablemente no deber\u00edamos usarlo, \u00bfverdad? Bueno, no del todo.<\/p>\n

Se podr\u00eda decir algo similar sobre los autom\u00f3viles. En las manos equivocadas, son un arma mortal. La gente los usa en ataques de ariete y como veh\u00edculos de huida. \u00bfDeber\u00edamos todos dejar de usar autom\u00f3viles? No claro que no. Pero tienen que ser utilizados correctamente y por personas que sepan conducirlos.<\/p>\n

El adjetivo habitual aplicado a eval<\/code> es \u00abmal\u00bb. Pero todo se reduce a c\u00f3mo se usa. los eval <\/code> comando coteja el valores<\/em> de una o m\u00e1s variables. Crea una cadena de comando. Luego ejecuta ese comando. Esto lo hace \u00fatil cuando necesita hacer frente a situaciones en las que el contenido de un comando se deriva din\u00e1micamente durante la ejecuci\u00f3n de su secuencia de comandos.<\/p>\n

Los problemas surgen cuando se escribe un script para usar eval<\/code> en una cadena que se ha recibido de alg\u00fan lugar fuera de<\/em> la secuencia de comandos. Puede ser ingresado por un usuario, enviado a trav\u00e9s de una API, etiquetado en una solicitud HTTPS o en cualquier otro lugar externo al script.<\/p>\n

Si la cadena que eval<\/code> va a funcionar no se deriv\u00f3 localmente y mediante programaci\u00f3n, existe el riesgo de que la cadena contenga instrucciones maliciosas incrustadas u otra entrada mal formada. Obviamente, no quieres eval<\/code> para ejecutar comandos maliciosos. Entonces, para estar seguro, no use eval<\/code> con cadenas generadas externamente o entrada del usuario.<\/p>\n

Primeros pasos con eval<\/h2>\n

los eval<\/code> El comando es un comando de shell Bash incorporado. Si Bash est\u00e1 presente, eval<\/code> estar\u00e1 presente.<\/p>\n

eval<\/code> concatena sus par\u00e1metros en una sola cadena. Utilizar\u00e1 un solo espacio para separar elementos concatenados. Eval\u00faa los argumentos y luego pasa la cadena completa al shell para ejecutar.<\/p>\n

Vamos a crear una variable llamada wordcount<\/code>.<\/p>\n

wordcount=\"wc -w raw-notes.md\"<\/pre>\n

La variable de cadena contiene un comando para contar las palabras en un archivo llamado \u00abraw-notes.md\u00bb.<\/p>\n

Nosotros podemos usar eval<\/code> para ejecutar ese comando pas\u00e1ndole el valor<\/em> de la variable<\/p>\n

\"Usando<\/p>\n

El comando se ejecuta en el shell actual, no en un subshell. Podemos mostrar esto f\u00e1cilmente. Tenemos un archivo de texto corto llamado \u00abvariables.txt\u00bb. Contiene estas dos l\u00edneas.<\/p>\n

first=How-To
\nsecond=Geek<\/pre>\n

usaremos cat<\/code> para enviar estas l\u00edneas a la ventana del terminal. Entonces usaremos eval<\/code> para evaluar un cat<\/code> comando para que se act\u00fae sobre las instrucciones dentro del archivo de texto. Esto establecer\u00e1 las variables para nosotros.<\/p>\n

cat variables.txt
\neval \"$(cat variables.txt)\"
\necho $first $second<\/pre>\n

\"Acceso<\/p>\n

Mediante el uso echo<\/code> para imprimir los valores de las variables podemos ver que eval<\/code> El comando se ejecuta en el shell actual, no en un subshell.<\/p>\n

Un proceso en una subcapa no puede cambiar el entorno de la capa principal. Debido a que eval se ejecuta en el shell actual, las variables establecidas por eval<\/code> son utilizables desde el shell que lanz\u00f3 el eval<\/code> dominio.<\/p>\n

Tenga en cuenta que si utiliza eval<\/code> en un script, el caparaz\u00f3n que ser\u00eda alterado por eval<\/code> es el subshell en el que se ejecuta el script, no el shell que lo inici\u00f3.<\/p>\n

RELACIONADO:<\/strong> C\u00f3mo usar los comandos cat y tac de Linux<\/em><\/strong><\/p>\n

Uso de variables en la cadena de comandos<\/h2>\n

Podemos incluir otras variables en las cadenas de comandos. Estableceremos dos variables para contener n\u00fameros enteros.<\/p>\n

num1=10 
\nnum2=7<\/pre>\n

Crearemos una variable para contener un expr<\/code> comando que devolver\u00e1 la suma de dos n\u00fameros. Esto significa que necesitamos acceder a los valores de las dos variables enteras en el comando. Tenga en cuenta los acentos graves alrededor de la expr<\/code> declaraci\u00f3n.<\/p>\n

add=\"`expr $num1 + $num2`\"<\/pre>\n

Crearemos otro comando para que nos muestre el resultado de la expr<\/code> declaraci\u00f3n.<\/p>\n

show=\"echo\"<\/pre>\n

Tenga en cuenta que no necesitamos incluir un espacio al final del echo<\/code> cadena, ni al comienzo de la expr<\/code> cuerda. eval<\/code> se encarga de eso.<\/p>\n

Y para ejecutar todo el comando usamos:<\/p>\n

eval $show $add<\/pre>\n

\"Uso<\/p>\n

Los valores de las variables dentro de la expr<\/code> cadena se sustituyen en la cadena por eval<\/code> antes de que se pase al shell para que se ejecute.<\/p>\n

RELACIONADO:<\/strong> C\u00f3mo trabajar con variables en Bash<\/em><\/strong><\/p>\n

Acceso a variables dentro de variables<\/h2>\n

Puede asignar un valor a una variable y luego asignar el nombre<\/em> de esa variable a otra variable. Usando eval<\/code>puede acceder a la valor<\/em> contenida en la primera variable, de su nombre que es el valor<\/em> almacenado en la segunda variable. Un ejemplo le ayudar\u00e1 a desenredar eso.<\/p>\n

Copie este script en un editor y gu\u00e1rdelo como un archivo llamado \u00abassign.sh\u00bb.<\/p>\n

#!\/bin\/bash
\n
\ntitle=\"How-To Geek\"
\nwebpage=title
\ncommand=\"echo\"
\neval $command $$webpage<\/pre>\n

Tenemos que hacerlo ejecutable con el chmod<\/code> dominio.<\/p>\n

chmod +x assign.sh<\/pre>\n

\"Usando<\/p>\n

Deber\u00e1 hacer esto para cualquier secuencia de comandos que copie de este art\u00edculo. Simplemente use el nombre de script apropiado en cada caso.<\/p>\n

Cuando ejecutamos nuestro script vemos el texto de la variable title<\/code> a pesar de eval<\/code> el comando est\u00e1 usando la variable webpage<\/code>.<\/p>\n

.\/assign.sh<\/pre>\n

\"Acceder<\/p>\n

El signo de d\u00f3lar escapado\u201d$<\/code>\u00aby los frenos\u00bb<\/code>\u201d hacer que eval mire el valor contenido dentro de la variable cuyo nombre est\u00e1 almacenado en el webpage<\/code> variable.<\/p>\n

Uso de variables creadas din\u00e1micamente<\/h2>\n

Nosotros podemos usar eval<\/code> para crear variables din\u00e1micamente. Este script se llama \u00abloop.sh\u00bb.<\/p>\n

#!\/bin\/bash
\n
\ntotal=0
\nlabel=\"Looping complete. Total:\"
\n
\nfor n in 1..10
\ndo
\n  eval x$n=$n
\n  echo \"Loop\" $x$n
\n  ((total+=$x$n))
\ndone
\n
\necho $x1 $x2 $x3 $x4 $x5 $x6 $x7 $x8 $x9 $x10
\n
\necho $label $total<\/pre>\n

Crea una variable llamada total<\/code> que contiene la suma de los valores de las variables que creamos. Luego crea una variable de cadena llamada label<\/code>. Esta es una simple cadena de texto.<\/p>\n

Vamos a repetir 10 veces y crear 10 variables llamadas x1<\/code> hasta x10<\/code>. los eval<\/code> declaraci\u00f3n en el cuerpo del bucle proporciona la \u00abx\u00bb y toma el valor del contador del bucle $n<\/code> para crear el nombre de la variable. Al mismo tiempo, establece la nueva variable en el valor del contador de bucle. $n<\/code>.<\/p>\n

Imprime la nueva variable en la ventana del terminal y luego incrementa la total<\/code> variable con el valor de la nueva variable.<\/p>\n

Fuera del ciclo, las 10 nuevas variables se imprimen una vez m\u00e1s, todas en una l\u00ednea. Tenga en cuenta que tambi\u00e9n podemos referirnos a las variables por sus nombres reales, sin usar una versi\u00f3n calculada o derivada de sus nombres.<\/p>\n

Finalmente, imprimimos el valor de la total<\/code> variable.<\/p>\n

.\/loop.sh<\/pre>\n

\"Usando<\/p>\n

RELACIONADO:<\/strong> Introducci\u00f3n: Bash Loops: for, while y till<\/em><\/strong><\/p>\n

Uso de eval con arreglos<\/h2>\n

Imagine un escenario en el que tiene un script que se ejecuta durante mucho tiempo y realiza alg\u00fan procesamiento por usted. Escribe en un archivo de registro con un nombre creado a partir de una marca de tiempo. De vez en cuando, se iniciar\u00e1 un nuevo archivo de registro. Cuando finaliza el script, si no ha habido errores, borra los archivos de registro que ha creado.<\/p>\n

No quieres que simplemente rm *.log<\/code>, solo desea que elimine los archivos de registro que ha creado. Este script simula esa funcionalidad. Esto es \u00abclear-logs.sh\u00bb.<\/p>\n

#!\/bin\/bash
\n
\ndeclare -a logfiles
\n
\nfilecount=0 
\nrm_string=\"echo\"
\n
\nfunction create_logfile() 
\n  ((++filecount))
\n  filename=$(date +\"%Y-%m-%d_%H-%M-%S\").log
\n  logfiles[$filecount]=$filename
\n  echo $filecount \"Created\" $logfiles[$filecount]
\n
\n
\n# body of the script. Some processing is done here that
\n# periodically generates a log file. We'll simulate that
\ncreate_logfile
\nsleep 3
\ncreate_logfile
\nsleep 3
\ncreate_logfile
\nsleep 3
\ncreate_logfile
\n
\n# are there any files to remove?
\nfor ((file=1; file<=$filecount; file++))
\ndo
\n  # remove the logfile
\n  eval $rm_string $logfiles[$file] \"deleted...\"
\n  logfiles[$file]=\"\"
\ndone<\/pre>\n

El script declara una matriz llamada logfiles<\/code> . Esto contendr\u00e1 los nombres de los archivos de registro creados por el script. Declara una variable llamada filecount<\/code> . Esto contendr\u00e1 la cantidad de archivos de registro que se han creado.<\/p>\n

Tambi\u00e9n declara una cadena llamada rm_string<\/code>. En un script del mundo real, esto contendr\u00eda el rm <\/code> comando, pero estamos usando echo<\/code> para que podamos demostrar el principio de una manera no destructiva.<\/p>\n

La funci\u00f3n create_logfile()<\/code> es donde se nombra cada archivo de registro y donde se abrir\u00eda. Solo estamos creando el Nombre del archivo<\/em>y simulando que se ha creado en el sistema de archivos.<\/p>\n

La funci\u00f3n incrementa la filecount<\/code> variable. Su valor inicial es cero, por lo que el primer nombre de archivo que creamos se almacena en la posici\u00f3n uno de la matriz. Esto se hace a prop\u00f3sito, como veremos m\u00e1s adelante.<\/p>\n

El nombre del archivo se crea usando el date<\/code> comando y la extensi\u00f3n \u201c.log\u201d. El nombre se almacena en la matriz en la posici\u00f3n indicada por filecount<\/code>. El nombre se imprime en la ventana del terminal. En un script del mundo real, tambi\u00e9n crear\u00eda el archivo real.<\/p>\n

El cuerpo del script se simula usando el sleep<\/code> dominio. Crea el primer archivo de registro, espera tres segundos y luego crea otro. Crea cuatro archivos de registro, espaciados para que las marcas de tiempo en sus nombres de archivo sean diferentes.<\/p>\n

Finalmente, hay un bucle que elimina los archivos de registro. El archivo de contador de bucles se establece en uno. Cuenta hasta e incluyendo el valor de filecount<\/code>que contiene el n\u00famero de archivos que se crearon.<\/p>\n

Si filecount<\/code> todav\u00eda est\u00e1 establecido en cero, porque no se crearon archivos de registro, el cuerpo del bucle nunca se ejecutar\u00e1 porque uno no es menor o igual que cero. es por eso que el filecount<\/code> la variable se estableci\u00f3 en cero cuando se declar\u00f3 y por qu\u00e9 se increment\u00f3 antes de<\/em> se cre\u00f3 el primer archivo.<\/p>\n

Dentro del ciclo, usamos eval<\/code> con nuestro no destructivo rm_string<\/code> y el nombre del archivo que se recupera de la matriz. Luego establecemos el elemento de la matriz en una cadena vac\u00eda.<\/p>\n

Esto es lo que vemos cuando ejecutamos el script.<\/p>\n

.\/clear-logs.sh<\/pre>\n

\"Eliminaci\u00f3n<\/p>\n

No todo es malo<\/h2>\n

muy difamado eval<\/code> definitivamente tiene sus usos. Como la mayor\u00eda de las herramientas, si se usa de manera imprudente, es peligrosa y en m\u00e1s de un sentido.<\/p>\n

Si se asegura de que las cadenas en las que funciona se crean internamente y no se capturan de humanos, API o cosas como solicitudes HTTPS, evitar\u00e1 las principales trampas.<\/p>\n

RELACIONADO:<\/strong> C\u00f3mo mostrar la fecha y la hora en la terminal de Linux (y usarla en scripts Bash)<\/em><\/strong><\/p>\n<\/div>\n