Вопрос Как читать символы, разделенные строки из переменной, преобразовывать в числа и выполнять арифметику?


В сценарии bash я хочу передать строку, содержащуюся в переменной, и содержать до 3 подстрок, разделенных символом «+». Каждая подстрока будет иметь определенное числовое значение, похожее на восьмеричный режим.

Я хотел бы разбить строку на подстроки, преобразовать их в их числовое значение и добавить значения вместе.

Например, если мои подстроки и значения:

  • hat = 1
  • рубашка = 2
  • брюки = 4

И моя переменная, содержащая их в строке:

my_outfit=shirt+trousers

Я бы хотел, чтобы переменная называлась outfit_value чтобы иметь значение 6. Как мне это сделать?

Я думал о настройке IFS на «+» и чтение переменной в массив, затем цикл через массив и преобразование каждого элемента в его значение. К сожалению, моя голова превращается в заварной крем, когда я думаю об извлечении этих элементов числового значения и выполнении арифметического выражения.

РЕДАКТИРОВАТЬ:

Это то, что у меня до сих пор, похоже, работает, но я хотел бы знать, есть ли какие-либо проблемы, или если это можно сделать более безопасно / эффективно:

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"

3
2018-05-04 12:39


происхождения


Итак, как выглядит фактическая переменная? Где хранятся соответствующие значения (массив, другие переменные)? - Sergiy Kolodyazhnyy
@serg отредактировал с моей попыткой! - Arronical


ответы:


При использовании bash в контексте арифметической оценки имена переменных не требуют $ префикс. Это означает, что это возможно:

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

# evaluate the equation 
(( $string ))

echo $my_outfit

выходы

6

4
2018-05-04 13:43



Обратите внимание, что это описано в руководстве в Арифметика оболочки раздел. См. Первый абзац, следующий за списком операторов. - glenn jackman


Вот вариант вашего исходного метода, но с использованием массивов bash. Обратите внимание, что нет необходимости сохранять восстановление разделителя полей - вы можете просто назначить временное значение, когда вы read Струна

#!/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"

2
2018-05-04 20:42



Спасибо, это помогло улучшить мое понимание ассоциативных массивов и имеет бонус, что я могу выполнять другие операции над элементами в массиве my_items во время цикла for. - Arronical