Atribuir linha específica de uma variável para outra variável

3

Eu gostaria de pegar uma linha específica de uma variável para outra variável. Eu tentei isso, mas não funciona:

c="1.apple
2.banna
3.peach"

read "Please choose fruit [1-3]:" t

a=$c | awk "NR==$t"
echo "You choose: $a"

Qual é o meu erro?

    
por Zion Levi 18.01.2015 / 09:35

2 respostas

5

Use Aqui redirecionamento de string <<< junto com Substituição de comando $() e não se esqueça de coloca aspas duplas em torno de suas variáveis :

a=$(awk "NR==$t" <<< "$c")
    
por 18.01.2015 / 11:23
1

Em primeiro lugar:

read "Please choose fruit [1-3]:" t

... não funcionará. Parece que você está tentando fornecer uma string de prompt para o shell embutido read , mas read interpreta seu primeiro argumento como o nome de uma variável para atribuir o valor da linha que lê de stdin a menos que seja entregue opções .

read -p "Please choose fruit [1-3]:" t

... é uma opção suportada em muitos shells e provavelmente está mais próxima do que você pretende fazer.

Dito isso, você provavelmente não deve empilhar vários valores em uma atribuição individualmente delimitada, a menos que você tenha estabelecido um meio para dividi-lo. Quando você faz:

var=' some list of things '

O shell acabará por analisar isso como:

set apple banana peach
some list of things
printf %s\n "$1"

... e atribua o nome único ao valor único. Muitas shells oferecem formas mais avançadas de delimitação - como matrizes nomeadas - mas todas as shells POSIX fornecem pelo menos um array facilmente definível por contexto de função - a matriz $@ shell. Várias implementações que fornecem matrizes nomeadas geralmente imitam o comportamento do array $@ shell para suas matrizes nomeadas também.

Portanto, em vez de atribuir todos esses valores individuais a uma única string, você pode fazer isso:

apple

Você pode testemunhar o efeito disso, endereçando cada valor individual individualmente pelo número como:

printf %d\n "$#"

... que imprime:

3

Observação - se você usar valores maiores que 9, é melhor incluir a referência entre chaves como "${10}"

Você pode endereçar o número de diferentes strings em "$#" como:

printf %s\n "$@"

... que imprime ...

apple
banana
peach

Você pode endereçar o lote deles em uma lista de strings separadas, como:

printf %s\n "$*"

... que imprime:

apple banana peach

... ou como uma única string concatenada como:

IFS='fruit sucks'; printf %s\n "$*"

... onde as strings de valor de matriz separadas são concatenadas no primeiro caractere contido na variável de shell $IFS . Portanto, se você tiver um valor $IFS padrão de <space><tab><newline> , cada string da matriz será unida à próxima com um único <space> entre elas. O comando acima, por exemplo, imprime:

applefbananafpeach

... mas se eu fizer isso:

array=( apple banana peach )

... imprime:

array[0]=apple array[1]=banana array[2]=peach

A maioria dos shells que implementam extensões de array nomeadas o fazem com sintaxe semelhante, exceto que os vários meios de endereçar o array devem estar associados a um nome. Uma atribuição de matriz normalmente se parece com:

set apple banana peach; n=0
{   for a do printf "$((n+=1)).:\t%s\n" "$a"; done
    printf "Please choose fruit [1-$#]: "; read t
} <>/dev/tty >&0 &&
[ "0$((!${#t}))" -lt "0${t##*[!0-9]*}" ] &&
eval 'printf "You choose: %s\n" "${'"$t"}\"

... ou ...

read "Please choose fruit [1-3]:" t

Em comparação com as matrizes "$1" , "$#" , "$@" , "$*" , normalmente funcionam como "${array[1]}" , "${#array[@]}" , "${array[@]}" e "${array[*]}" , onde a relação mencionada anteriormente entre "$*" e "$IFS" ainda são verdadeiros para "${array[*]}" .

Depois de ter delimitado corretamente seus valores, seu problema se torna muito mais fácil de lidar:

read -p "Please choose fruit [1-3]:" t

Alguns podem zombar do uso de eval acima, mas seu uso aqui não é menos seguro do que muitos poderiam fazer como "${array[$t]}" (que é uma maneira de fazer isso com matrizes nomeadas) porque "${array[$t]}" implica uma segunda avaliação de $t como um índice depois de ser analisado pela primeira vez como uma string. Sem testá-lo como faço acima para garantir que ele contenha pelo menos um e nada além de um dígito e que seja maior que 0 (ou qualquer que seja o índice de array com o nome mínimo da implementação do shell) poderia render resultados não intencionais.

    
por 18.01.2015 / 19:29