Acho que é isso que você está tentando fazer:
line='dog,/path1,/path2'
IFS=', ' read -r -a dog <<< "$line"
echo "$dog"
dog
echo "${dog[1]}"
/path1
echo "${dog[2]}"
/path2
Isto assume que o seu shell é bash.
Eu tenho uma variável que tem um valor como este
line=dog,/path1,/path2
O que eu quero é criar uma variável a partir do valor; Por exemplo, dog
deve ser a variável e deseja obter a saída abaixo:
dog=/path1,/path2
dog1=/path1
dog2=/path2
Da mesma forma, se eu tiver line=bull,/val1,/val2
, preciso da saída abaixo
bull=/val1,/val2
bull1=/val1
bull2=/val2
Observe que line
terá apenas três valores separados por vírgulas.
Aqui está uma solução centrada no 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]}"
A primeira linha divide sua variável $line
em partes com base nas vírgulas. A segunda linha, trabalhando de dentro para fora:
1
, sinal de igual e, em seguida, o segundo valor, 2
, sinal de igual e, em seguida, o terceiro valor printf
dessas três cadeias, separadas por novas linhas. Esta resposta é, como sua pergunta, codificada para ter três valores em $line
.
Exemplo de entrada & saída (os $
iniciais são os prompts do 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
Você pode redirecionar a saída do printf para um arquivo com facilidade suficiente.
Se você estiver usando bash
, poderá fazer algo assim (com extrações echo
extras para mostrar o que está acontecendo em 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
Isso usa perl
para dividir $line
por vírgulas. O primeiro campo é salvo em $var
, o restante em uma matriz chamada @values
. Em seguida, produz saída adequada para uso com o comando bash declare
para definir variáveis.
Observe que $newline
não é e não deve ser colocado naspas duplas na linha declare
. Se tiver aspas duplas, declare
obterá apenas um argumento em vez de três separados por espaços.
Um efeito colateral desagradável da falta de cotação aqui é que a declare
WILL falhará se qualquer um dos valores de campo contiver caracteres de espaço etc. %código%. Você pode corrigir isso, se necessário, gerando citações apropriadas das instruções line=dog,/path /with / spaces,/path2
e print
no script printf
. E / ou definindo perl
como uma matriz bash em vez de uma string. Deixado como um exercício para o leitor, como já mostrei o princípio / técnica que está sendo usado aqui.
Se você quiser que eles sejam declarados como variáveis exportadas, use:
declare -x $newline
veja $newline
para mais detalhes.
BTW, em help declare
, você pode usar ksh
em vez de typeset
. declare
também é suportado por typeset
, mas considerado obsoleto (consulte bash
in help typeset
).
Por fim: tem certeza de que você não preferiria usar uma variável de matriz shell (por exemplo, bash
, dog[0]=/path1,/path2
e dog[1]=/path1
) em vez de variáveis separadas?
Este é o tipo de coisa para a qual eles existem.
Você poderia fazer algo assim. Eu defino a linha como você tem. Em seguida, analiso nosso primeiro token separado por vírgula da linha (suponho que aqui será válido para um nome de variável). Em seguida, construo duas novas variáveis com base no primeiro token e atribuo-as aos segundo e terceiro tokens separados por vírgula da linha.
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
Tags text-processing shell variable