Crie texto correspondente a múltiplas atribuições de variáveis ​​a partir de uma única variável

Crie texto correspondente a múltiplas atribuições de variáveis ​​a partir de uma única variável

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, dogdeve 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,/val2precisar da saída abaixo

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

Observe que lineterá 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 $linevariável em partes com base nas vírgulas. A segunda linha, trabalhando de dentro para fora:

  1. gera o primeiro valor (por exemplo, 'cachorro'), sinal de igual, depois os dois segundos valores,
  2. gera o primeiro valor com o sufixo 1, sinal de igual e, em seguida, o segundo valor,
  3. gera o primeiro valor, com o sufixo de 2, sinal de igual e, em seguida, o terceiro valor,
  4. printfessas 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 echoinstruçõ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 perlser dividido $linepor 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 declarecomando bash para definir variáveis.

Observe que $newlinenão está e não deve estar entre aspas duplas na declarelinha. Se estiver entre aspas duplas, declareobterá 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 printe printfno perlscript. E/ou definindo $newlinecomo 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 declarepara mais detalhes.

Aliás, em ksh, você pode usar typesetem vez de declare. typesettambém é suportado, bashmas considerado obsoleto (ver help typesetem 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

informação relacionada