Como ler strings separadas por símbolos de uma variável, converter em números e realizar aritmética?

3

Em um script bash, desejo passar uma string contida em uma variável e conter até 3 substrings separadas pelo símbolo '+'. Cada substring terá um valor numérico específico, como um modo octal.

Gostaria de dividir a string nas substrings, convertê-las em seu valor numérico e adicionar os valores juntos.

Por exemplo, se minhas substrings e valores forem:

  • hat = 1
  • shirt = 2
  • calças = 4

E minha variável contendo estes em uma string é:

my_outfit=shirt+trousers

Eu gostaria que uma variável chamada outfit_value tivesse um valor de 6. Como devo fazer isso?

Pensei em definir IFS para '+' e ler a variável em uma matriz, depois fazer o loop pela matriz e converter cada elemento em seu valor. Infelizmente, minha cabeça se transforma em creme quando penso em recuperar esses elementos de valor numérico e fazer uma expressão aritmética.

EDITAR:

Isto é o que tenho até agora, parece funcionar, mas gostaria de saber se há algum problema, ou se poderia ser feito de forma mais segura / eficiente:

my_outfit=hat+shirt+trousers

oIFS=$IFS
IFS=+
read -a clothes <<< "$my_outfit"
IFS=$oIFS

outfit_value=0

for string in ${clothes[@]}
do
   if [[ $string = "hat" ]]
   then
      add_value=1
   elif [[ $string = "shirt" ]]
   then
      add_value=2
   elif [[ $string = "trousers" ]]
   then
      add_value=4
   fi
   let outfit_value="$outfit_value"+"$add_value"
done

echo "OUTFIT VALUE is $outfit_value"
    
por Arronical 04.05.2016 / 14:39

2 respostas

4

Com o bash, em um contexto de avaliação aritmética, os nomes das variáveis não exigem o prefixo $ . Isso significa que isso é possível:

# set up the variables
hat=1 shirt=2 trousers=4
string="my_outfit=shirt+trousers"

# evaluate the equation 
(( $string ))

echo $my_outfit

saídas

6
    
por glenn jackman 04.05.2016 / 15:43
2

Aqui está uma variante do seu método original, mas usando matrizes bash. Note que não há necessidade de salvar uma restauração do separador de campo - você pode simplesmente atribuir um valor temporário quando você read da string

#!/bin/bash

# create a map (lookup table) from items to values
declare -A values=( [hat]=1 [shirt]=2 [trousers]=4 )
# (an ASSOCIATIVE array)

my_outfit='hat+shirt+trousers'

# convert the string to a simple (INDEXED) array
IFS=+ read -r -a my_items <<< "$my_outfit"

# loop over the array of items, looking up and summing the values 
outfit_value=0
for item in "${my_items[@]}"; do
  ((outfit_value += values[$item]))
done

printf 'OUTFIT VALUE is %s\n' "$outfit_value"
    
por steeldriver 04.05.2016 / 22:42

Tags