Crear texto correspondiente a múltiples asignaciones de variables a partir de una sola variable

Crear texto correspondiente a múltiples asignaciones de variables a partir de una sola variable

Tengo una variable que tiene un valor como este.

line=dog,/path1,/path2

Lo que quiero es crear una variable a partir del valor; es decir dog, debería ser la variable y desea obtener el siguiente resultado:

dog=/path1,/path2
dog1=/path1
dog2=/path2

Del mismo modo, si tengo, line=bull,/val1,/val2necesito el siguiente resultado.

bull=/val1,/val2
bull1=/val1
bull2=/val2

Tenga en cuenta que linetendrá sólo tres valores separados por comas.

Respuesta1

Creo que eso es lo que estás intentando hacer:

line='dog,/path1,/path2'
IFS=', ' read -r -a dog <<< "$line"

echo "$dog"
dog
echo "${dog[1]}"
/path1
echo "${dog[2]}"
/path2 

Esto supone que tu shell es bash.

Respuesta2

Aquí hay una solución centrada en bash:

IFS=, read -r -a vars <<<"$line"
printf "%s\n" "${vars[0]}=${vars[1]},${vars[2]}" "${vars[0]}1=${vars[1]}" "${vars[0]}2=${vars[2]}"

La primera línea divide su $linevariable en partes según las comas. La segunda línea, trabajando de adentro hacia afuera:

  1. genera el primer valor (por ejemplo, 'perro'), signo igual, luego los dos segundos valores,
  2. genera el primer valor con el sufijo 1, signo igual, luego el segundo valor,
  3. genera el primer valor, con el sufijo 2, signo igual, luego el tercer valor,
  4. printfesas tres cadenas, separadas por nuevas líneas.

Esta respuesta está, como su pregunta, codificada para tener tres valores en $line.

Entrada y salida de muestra (las principales $son las indicaciones del shell):

$ line=dog,/path1,/path2
$ IFS=, read -r -a vars <<<"$line"
$ printf "%s\n" "${vars[0]}=${vars[1]},${vars[2]}" "${vars[0]}1=${vars[1]}" "${vars[0]}2=${vars[2]}"
dog=/path1,/path2
dog1=/path1
dog2=/path2

Puede redirigir la salida de printf a un archivo con bastante facilidad.

Respuesta3

Si está utilizando bash, puede hacer algo como esto (con echodeclaraciones adicionales para mostrar lo que sucede en cada etapa):

$ line=dog,/path1,/path2

$ newline=$(printf "%s\n" "$line" | 
            perl -n -e 'BEGIN {$count=1};
                        my ($var,@values) = split /,/;
                        print "$var=" . join(",",@values);
                        foreach (@values) {
                            printf "%s%i=\"%s\" ",$var, $count++, $_
                        }')

$ echo "$newline"
dog=/path1,/path2 dog1=/path1 dog2=/path2

$ declare $newline

$ declare | grep '^dog'
dog=/path1,/path2
dog1=/path1
dog2=/path2

Esto se utiliza perlpara dividir $linepor comas. El primer campo se guarda en $var, el resto en una matriz llamada @values. Luego produce una salida adecuada para usar con el declarecomando bash para establecer variables.

Tenga en cuenta que $newlineno está ni debe estar entre comillas dobles en la declarelínea. Si está entre comillas dobles, declaresolo obtendrá un argumento en lugar de tres separados por espacios.

Un efecto secundario desagradable de la falta de citas aquí es que eldeclare VOLUNTADfalla si alguno de los valores de campo contiene caracteres de espacio, etc., por ejemplo line=dog,/path /with / spaces,/path2. Puede solucionar este problema si es necesario generando citas apropiadas de las declaraciones printy printfen el perlscript. Y/o definiéndolo $newlinecomo una matriz bash en lugar de una cadena. Se deja como ejercicio para el lector, ya que ya he mostrado suficiente del principio/técnica que se utiliza aquí.

Si desea que se declaren como variables exportadas, utilice:

declare -x $newline

ver help declarepara más detalles.

Por cierto, en ksh, puedes usar typeseten lugar de declare. typesettambién es compatible con bashpero se considera obsoleto (ver help typeseten bash).


Finalmente: ¿está seguro de que no preferiría utilizar una variable de matriz de shell (por ejemplo dog[0]=/path1,/path2, dog[1]=/path1y dog[2]=/path2) en lugar de variables separadas? Este es el tipo de cosas para las que existen.

Respuesta4

Podrías hacer algo como esto. Defino la línea como la tienes tú. A continuación, analizo el primer token separado por comas de la línea (supongo que será válido para un nombre de variable). Luego construyo dos nuevas variables basadas en el primer token y las asigno al segundo y tercer tokens separados por comas de la línea.

line="dog,/path1,/path2"
first="$(echo "${line}" | awk -F, '{ print $1 }')"
eval "${first}1=$(echo "${line}" | awk -F, '{ print $2 }')"
eval "${first}2=$(echo "${line}" | awk -F, '{ print $3 }')"

echo "${dog1}"
/path1
echo "${dog2}"
/path2

información relacionada