
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; ou seja, 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 line=bull,/val1,/val2
precisar da saída abaixo
bull=/val1,/val2
bull1=/val1
bull2=/val2
Observe que line
terá apenas três valores separados por vírgulas.
Responder1
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
Isso pressupõe que seu shell seja bash.
Responder2
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 $line
variável em partes com base nas vírgulas. A segunda linha, trabalhando de dentro para fora:
- gera o primeiro valor (por exemplo, 'cachorro'), sinal de igual, depois os dois segundos valores,
- gera o primeiro valor com o sufixo
1
, sinal de igual e, em seguida, o segundo valor, - gera o primeiro valor, com o sufixo de
2
, sinal de igual e, em seguida, o terceiro valor, printf
essas três strings, separadas por novas linhas.
Esta resposta é, como sua pergunta, codificada para ter três valores em $line
.
Exemplo de entrada e saída (os principais $
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 bastante facilidade.
Responder3
Se estiver usando bash
, você pode fazer algo assim (com echo
instruções extras para mostrar o que está acontecendo em cada estágio):
$ 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 costuma perl
ser dividido $line
por vírgulas. O primeiro campo é salvo em $var
, o restante em uma matriz chamada @values
. Em seguida, produz uma saída adequada para uso com o declare
comando bash para definir variáveis.
Observe que $newline
não está e não deve estar entre aspas duplas na declare
linha. Se estiver entre aspas duplas, declare
obterá apenas um argumento em vez de três separados por espaços.
Um efeito colateral desagradável da falta de citações aqui é que odeclare
VAIfalhará se algum dos valores do campo contiver caracteres de espaço, etc., por exemplo line=dog,/path /with / spaces,/path2
. Você pode corrigir isso, se necessário, gerando citações apropriadas das instruções print
e printf
no perl
script. E/ou definindo $newline
como um array bash em vez de uma string. Deixei como exercício para o leitor, pois já mostrei bastante do princípio/técnica que está sendo utilizado aqui.
Se você quiser que elas sejam declaradas como variáveis exportadas, use:
declare -x $newline
veja help declare
para mais detalhes.
Aliás, em ksh
, você pode usar typeset
em vez de declare
. typeset
também é suportado, bash
mas considerado obsoleto (ver help typeset
em bash
).
Finalmente: você tem certeza de que não prefere usar uma variável de array shell (por exemplo dog[0]=/path1,/path2
, dog[1]=/path1
, e dog[2]=/path2
) em vez de variáveis separadas? É para esse tipo de coisa que eles existem.
Responder4
Você poderia fazer algo assim. Eu defino a linha como você fez. Em seguida, analiso nosso primeiro token separado por vírgula da linha (presumo aqui que será válido para um nome de variável). Em seguida, construo duas novas variáveis com base no primeiro token e atribuo-as ao segundo e ao 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