script bash con parametros con espacio

publicado por: Anonymous

estoy haciendo un script de bash pero tengo unas variables que necesitan espacios como el nombre, como puedo hacerle para que un espacio no lo tome como otro parámetro ejemplo

#!/bin/bash
mkdir $1
cp -a /home/x/Descargas/archivo.zip /var/www/html/
unzip /var/www/html/$1 /var/www/html/$1/
php /var/www/html/$1/install/index_cli.php --domain=$1 --db_server=$2 --db_name=$1 --prefix=$3 --db_user=$4 --db_password=$5 --email=$6 --name=$7 

al momento que lo corro es algo así
sudo ./script.sh varlor1 valor2 valor4 valor5 valor6 valor7

pero que fuera algo así
sudo ./script.sh -valor 2 -valor3 -va lor4 etc
que pueda introducir espacios y no me tome el siguiente parámetro hasta que no se separe con un – gracias

solución

La variables IFS (internal field separator) determina el comportamiento de lo que ingreses como argumentos, esa variable cambia dependiendo de la shell que uses. Si usas bash, el IFS es <espacio><tab><salto de línea>, en cambio, si usas zsh es <espacio><tab><salto de línea><carácter nulo>.

Como prueba de esto puedes correr $ echo -n "$IFS" | od -cb en tu terminal y ver lo que comento.

La variable IFS es una variable de ambiente (que la puedes editar por gusto, pero con cuidado) que las shells utilizan sus caracteres como separadores después de las expansiones (brace, pathname, command substitution, process substitution, variable expansion, etc).

Las comillas previenen 2 cosas: 1. Ciertas expansiones, por ejemplo, al usar “*” dentro de una variable previene que se expanda, 2. Evita que se divida según los caracteres descritos en el IFS.

Por lo tanto, tu script debería de quedar algo así.

#!/bin/bash

db_name="$1"
db_server="$2"
prefix="$3"
db_user="$4"
db_password="$5"
email="$6"
name="$7"

mkdir "$db_name"

cp -a /home/x/Descargas/archivo.zip /var/www/html/

unzip /var/www/html/"$db_name" /var/www/html/"$db_name"/

php /var/www/html/"$db_name"/install/index_cli.php 
    --domain="$db_name" 
    --db_server="$db_server" 
    --db_name="$db_name" 
    --prefix="$prefix" 
    --db_user="$db_user" 
    --db_password="$db_password" 
    --email="$email" 
    --name="$name" 

Volviendo al tema del IFS. Si tu hicieras un script como este.

#!/bin/bash

echo "Parámetro 1: $1"

Y lo corrieras de la siguiente manera:

$ ./ifs.sh "$(echo -e "espacio: tabtsalto de lineanfin")"

El resultado respetaría los caracteres que ingresaste resultando algo así:

Parámetro 1: espacio: tab:      salto de linea:
fin

En cambio, si cambias tu script a esto (quitándole las comillas a la susbstitución de parámetro)

#!/bin/bash

echo "Parámetro 1:" $1

Y lo corres de la misma manera que el anterior, la salida resultaría así:

Parámetro 1: espacio: tab: salto de linea: fin

Es decir, utiliza los caracteres de la variable IFS para separar bloques de texto.

La documentación sobre este efecto la puedes consultar con man 1 bash en la sección de “QUOTING”.

Volviendo a tu forma de plantear tu petición, considero que tenías la inquietud de que los parámetros se tomen en cuenta dentro de tu programa dependiendo de un flag. Y concuerdo mucho en eso contigo, sólo que a mi me gusta que sea mucho más verboso para evitar confusiones entre los sysadmin y desarrolladores que usen el programa. Así que te sugiero que apliques la estrategia de poner parámetros con nombre, esto lo uso de la siguiente manera (me gusta más que usar getopts).

#!/bin/bash

# db_name="$1"
# db_server="$2"
# prefix="$3"
# db_user="$4"
# db_password="$5"
# email="$6"
# name="$7"

main() {

    while [[ $# > 0 ]]
    do
        case "$1" in

            --db_name )
                shift
                db_name="$1"
                shift
            ;;
            --db_server )
                shift
                db_server="$1"
                shift
            ;;
            --prefix )
                shift
                prefix="$1"
                shift
            ;;
            --db_user )
                shift
                db_user="$1"
                shift
            ;;
            --db_password )
                shift
                db_password="$1"
                shift
            ;;
            --email )
                shift
                email="$1"
                shift
            ;;
            --name )
                shift
                name="$1"
                shift
            ;;
            *)
                shift
            ;;
        esac
    done

    mkdir "$db_name"

    cp -a /home/x/Descargas/archivo.zip /var/www/html/

    unzip /var/www/html/"$db_name" /var/www/html/"$db_name"/

    php /var/www/html/"$db_name"/install/index_cli.php 
        --domain="$domain" 
        --db_server="$db_server" 
        --db_name="$db_name" 
        --prefix="$prefix" 
        --db_user="$db_user" 
        --db_password="$db_password" 
        --email="$email" 
        --name="$name" 

}

main "[email protected]"

Y, mientras mantengas entrecomilladas tus variables, te va a respetar todos los caracteres del IFS.

La forma de correr este programa (pensando en un ejemplo exagerado) sería algo así:

$ ./ifs.sh --db_name a --db_server b --prefix c --db_user d --db_password e --email "f espacios" --name "saltos
de linea"
Respondido por: Anonymous

Leave a Reply

Your email address will not be published. Required fields are marked *