Problema extraño al pasar variables desde un archivo de texto

Problema extraño al pasar variables desde un archivo de texto

Tengo un script que ejecuta otro script para cada línea de un archivo.

Cuando hago echocada uno $linepuedo ver el contenido completo de la línea como se esperaba.

connect.shSin embargo, solo el interior $1está configurado como user\ name.

Cuando intento usarlo "$line", $1termina connect.shsiendo user\ name user\ password.

¿Cómo puedo configurar el flujo del programa para que reboot.shpase cada línea /tmp/historycomo connect.sh2 parámetros?

¿Con el resultado final que $1es user\ namey $2es user\ password?

reiniciar.sh:

if [ -e "/tmp/history" ]; then
  while read -r line; do
    echo $line
    connect.sh $line \
      && break
  done </tmp/history
fi

conectar.sh:

echo $1
echo $2

/tmp/historia:

user\ name user\ password

Respuesta1

Supongo que las barras invertidas están ahí para escapar de los dos espacios y no separar los valores.

Con read -r lineobtienes toda la línea en la variable line, de modo que linecontiene user\ name user\ password, con los retrocesos. No es fácil dividir eso sin trucos eval. Un texto sin comillas $linese dividirá en espacios en blanco, con barras invertidas o no. Citado, se expande en una palabra, como viste.

Afortunadamente, readpuede manejar barras invertidas y dividir su entrada en dos (o más) variables. Esto haría que las variables contuvieran user namey user password(sin las barras invertidas):

while read user pass ; do 
    echo "user: $user"
    echo "pass: $pass"
    ./connect.sh "$user" "$pass"
done < file

Sin embargo, si desea permitir espacios en blanco en el nombre de usuario y la contraseña, podría ser mejor utilizar algún otro delimitador que no sea el espacio. Los dos puntos son comunes, por lo que tendrías una entrada como esta:

user name:user pass word

Y luego léelo con

while IFS=: read -r user pass ; do 
    echo "user: $user"
    echo "pass: $pass"
done < file          

(Eso debería funcionar siempre y cuando la contraseña no termine con dos puntos)

Respuesta2

Si tiene un argumento con espacios, deberá asegurarse de poner comillas dobles en la cadena para evitar connect.shque se interprete como argumentos múltiples. Es posible que desees dividir la cadena en varios argumentos. No estoy seguro de cuál es el formato de la línea, pero es posible que puedas hacer algo como esto:

line="user name user password"
# Split the line into space-separated tokens and store 1 and 2
UNAME=$(echo "$line" | cut -d ' ' -f 1,2)
# Split the line into space-separated tokens and store 3 and 4
UPASSWD=$(echo "$line" | cut -d ' ' -f 3,4)
echo "$UNAME"
echo "$UPASSWD"

Esto debería imprimir:

user name
user password

Probablemente necesitarás realizar algunos ajustes según el formato real de la línea de entrada. Por ejemplo, si su línea $ tiene el nombre de usuario y la contraseña de usuario separados por una coma, podría ejecutar:

line="user name,user password"
# Split the line into comma-separated tokens and store 1
UNAME=$(echo "$line" | cut -d ',' -f 1)
# Split the line into comma-separated tokens and store 2
UPASSWD=$(echo "$line" | cut -d ',' -f 2)
echo "$UNAME"
echo "$UPASSWD"

Sólo recuerda que si estás pasando un argumento a un programa y ese argumento tiene espacios, necesitarás usar comillas dobles para que el programa lo vea como un solo argumento.

información relacionada