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")
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?
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")
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.
Tags command-line bash awk shell variable