
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,/val2
necesito el siguiente resultado.
bull=/val1,/val2
bull1=/val1
bull2=/val2
Tenga en cuenta que line
tendrá 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 $line
variable en partes según las comas. La segunda línea, trabajando de adentro hacia afuera:
- genera el primer valor (por ejemplo, 'perro'), signo igual, luego los dos segundos valores,
- genera el primer valor con el sufijo
1
, signo igual, luego el segundo valor, - genera el primer valor, con el sufijo
2
, signo igual, luego el tercer valor, printf
esas 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 echo
declaraciones 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 perl
para dividir $line
por comas. El primer campo se guarda en $var
, el resto en una matriz llamada @values
. Luego produce una salida adecuada para usar con el declare
comando bash para establecer variables.
Tenga en cuenta que $newline
no está ni debe estar entre comillas dobles en la declare
línea. Si está entre comillas dobles, declare
solo 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 print
y printf
en el perl
script. Y/o definiéndolo $newline
como 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 declare
para más detalles.
Por cierto, en ksh
, puedes usar typeset
en lugar de declare
. typeset
también es compatible con bash
pero se considera obsoleto (ver help typeset
en bash
).
Finalmente: ¿está seguro de que no preferiría utilizar una variable de matriz de shell (por ejemplo dog[0]=/path1,/path2
, dog[1]=/path1
y 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