Cria texto correspondente a várias atribuições de variáveis de uma única variável

2

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.

    
por Alex Raj Kaliamoorthy 20.05.2016 / 15:44

4 respostas

2

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.

    
por 20.05.2016 / 15:51
2

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. exibe o primeiro valor (por exemplo, 'dog'), sinal de igual e, em seguida, os segundo dois valores,
  2. exibe o primeiro valor com sufixo de 1 , sinal de igual e, em seguida, o segundo valor,
  3. exibe o primeiro valor, com sufixo de 2 , sinal de igual e, em seguida, o terceiro valor
  4. 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.

    
por 20.05.2016 / 17:37
1

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.

    
por 20.05.2016 / 16:42
0

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
    
por 20.05.2016 / 16:56