Преобразование чисел в полные написанные слова

Вопрос или проблема

Мне нужно написать скрипт на Linux, который конвертирует числа в полные написанные слова. Из-за нехватки времени мне придется обойтись кодом без исключений и чисел после запятой, но он все равно не работает. Программа не распознает переменные, поэтому мне в основном нужна помощь с синтаксисом. Вот что у меня есть на данный момент (на нидерландском).

Обновление: Я перевел наиболее важную (как я считаю) часть на английский.

#!/bin/bash
echo -prijs "Введите цену: "
read price

thousands="expr $price /1000"
hundreds="expr ($price - $thousands) / 100"
teens="expr ($price - $hundreds - $thousands / 10"
units="expr $price - $hundreds - $thousands - $teens"

    for ((i=0 ; i<=$thousands; i++ ))
do
    case $thousands in
        0) echo -prijs "";;
        1) echo -prijs "тысяча";;
        2) echo -prijs "две тысячи";;
        3) echo -prijs "три тысячи";;
        4) echo -prijs "четыре тысячи";;
        5) echo -prijs "пять тысяч";;
        6) echo -prijs "шесть тысяч";;
        7) echo -prijs "семь тысяч";;
        8) echo -prijs "восемь тысяч";;
        9) echo -prijs "девять тысяч";;
        10) echo -prijs "десять тысяч";;
    esac
done
    for ((i=0 ; i<=$hundreds; i++ ))
do
    case $hundreds in
        0) echo -prijs "";;
        1) echo -prijs "сто";;
        2) echo -prijs "двести";;
        3) echo -prijs "триста";;
        4) echo -prijs "четыреста";;
        5) echo -prijs "пятьсот";;
        6) echo -prijs "шестьсот";;
        7) echo -prijs "семьсот";;
        8) echo -prijs "восемьсот";;
        9) echo -prijs "девятьсот";;
    esac
done
    for ((i=0 ; i<=$teens; i++ ))
do
    case $teens in
        0) echo -prijs "";;
        1) echo -prijs "десять";;
        2) echo -prijs "двадцать";;
        3) echo -prijs "тридцать";;
        4) echo -prijs "сорок";;
        5) echo -prijs "пятьдесят";;
        6) echo -prijs "шестьдесят";;
        7) echo -prijs "семьдесят";;
        8) echo -prijs "восемьдесят";;
        9) echo -prijs "девяносто";;
    esac
done
    for ((i=0 ; i<=$units; i++ ))
do
    case $units in
        0) echo -prijs "";;
        1) echo -prijs "один";;
        2) echo -prijs "два";;
        3) echo -prijs "три";;
        4) echo -prijs "четыре";;
        5) echo -prijs "пять";;
        6) echo -prijs "шесть";;
        7) echo -prijs "семь";;
        8) echo -prijs "восемь";;
        9) echo -prijs "девять";;
    esac
done

echo "Цена составляет: " 'expr $thousands + $hundreds + $teens + $units'

Для будущего себя и людей, ищущих эту команду.


Я наткнулся на эту команду, просматривая список вкладок:

spellout 1.0.11: конвертировать числа в названия чисел и денежные суммы
Использование: spellout [-l lang] [-p prefix] par1 [par2...]
Параметры: n: число; n-m: диапазон; n-m~s: диапазон с шагом
Примеры: spellout 1-10 500 1000-10000~1000
          spellout -l en-GB -p ordinal 1-100
          spellout -l en -p ordinal-number 1-100
          spellout -l en -p USD 100.45
          spellout -l en -p "money USD" 100.45
Справка модуля языка: spellout -l es help
Лицензия: GNU LGPL/BSD двойная лицензия

Я выяснил, что это (вероятно) происходит от Numbertext/libnumbertext и доступно в исходниках Debian


Пример:

$ spellout 39825
тридцать девять тысяч восемьсот двадцать пять
$ spellout -l de-DE 39825
neununddreißigtausendachthundertfünfundzwanzig
$ spellout -l en-US -p "money GBP" 39825
тридцать девять тысяч восемьсот двадцать пять фунтов стерлингов
$ spellout  -l de-DE -p ordinal 39825
neununddreißigtausendachthundertfünfundzwanzigste

На Ubuntu 24.04 вы можете установить и использовать его с:

sudo apt install libnumbertext-tools
/usr/lib/libnumbertext/spellout -l en 100

В вашем коде есть несколько проблем. Первая проблема в том, что вы используете одинарные кавычки, где следует использовать обратные кавычки. Вторая проблема в том, что expr на самом деле не нужен в bash, $(()) справится с задачей. Третья проблема в том, что формула просто неправильная. Четвертая проблема – это -prijs, как указано в комментарии. Перепишите эту часть вашего кода,

thousands="expr $price /1000"
hundreds="expr ($price - $thousands) / 100"
teens="expr ($price - $hundreds - $thousands / 10"
units="expr $price - $hundreds - $thousands - $teens"

на

thousands=$((price/1000))
hundreds=$((price%1000/100))
teens=$((price%100/10))
units=$((price%10))

где % – это оператор остатка в bash. Попробуйте исправить остальное (например, вещи с -prijs и последнюю строку вашего скрипта) самостоятельно.

Интересная задача. Вот мой вариант

#!/bin/bash

digits=(
    "" один два три четыре пять шесть семь восемь девять
    десять одиннадцать двенадцать тринадцать четырнадцать пятнадцать шестнадцать семнадцать восемьнадцать девятнадцать
)
tens=("" "" двадцать тридцать сорок пятьдесят шестьдесят семьдесят восемьдесят девяносто)
units=("" тысяча миллион миллиард триллион)

number2words() {
    local -i number=$((10#$1))
    local -i u=0
    local words=()
    local group

    while ((number > 0)); do
        group=$(hundreds2words $((number % 1000)) )
        [[ -n "$group" ]] && group="$group ${units[u]}"

        words=("$group" "${words[@]}")

        ((u++))
        ((number = number / 1000))
    done
    echo "${words[*]}"
}

hundreds2words() {
    local -i num=$((10#$1))
    if ((num < 20)); then
        echo "${digits[num]}"
    elif ((num < 100)); then
        echo "${tens[num / 10]} ${digits[num % 10]}"
    else
        echo "${digits[num / 100]} сто $("$FUNCNAME" $((num % 100)) )"
    fi
}

with_commas() {
    # sed -r ':a;s/^([0-9]+)([0-9]{3})/\1,\2/;ta' <<<"$1"
    # или, с помощью только bash
    while [[ $1 =~ ^([0-9]+)([0-9]{3})(.*) ]]; do
        set -- "${BASH_REMATCH[1]},${BASH_REMATCH[2]}${BASH_REMATCH[3]}"
    done
    echo "$1"
}

for arg; do
    [[ $arg == *[^0-9]* ]] && result="NaN" || result=$(number2words "$arg")
    printf "%s\t%s\n" "$(with_commas "$arg")" "$result"
done

В действии:

$ bash ./num2text.sh 9 98 987 9786 98765 987654 9876543 98765432 987654321 9876543210 98765432100 987654321000 9876543210000 98765432100000 987654321000000 1,234 x 1y z2
9       девять
98      девяносто восемь
987     девятьсот восемьдесят семь
9,786   девять тысяч семьсот восемьдесят шесть
98,765  девяносто восемь тысяч семьсот шестьдесят пять
987,654 девятьсот восемьдесят семь тысяч шестьсот пятьдесят четыре
9,876,543       девять миллионов восемьсот семьдесят шесть тысяч пятьсот сорок три
98,765,432      девяносто восемь миллионов семьсот шестьдесят пять тысяч четыреста тридцать два
987,654,321     девятьсот восемьдесят семь миллионов шестьсот пятьдесят четыре тысячи триста двадцать один
9,876,543,210   девять миллиардов восемьсот семьдесят шесть миллионов пятьсот сорок три тысячи двести десять
98,765,432,100  девяносто восемь миллиардов семьсот шестьдесят пять миллионов четыреста тридцать две тысячи сто
987,654,321,000 девятьсот восемьдесят семь миллиардов шестьсот пятьдесят четыре миллиона триста двадцать одна тысяча
9,876,543,210,000       девять триллионов восемьсот семьдесят шесть миллиардов пятьсот сорок три миллиона двести десять тысяч
98,765,432,100,000      девяносто восемь триллионов семьсот шестьдесят пять миллиардов четыреста тридцать две миллиона сто  тысяч
987,654,321,000,000     девятьсот восемьдесят семь триллионов шестьсот пятьдесят четыре миллиарда триста двадцать один миллион
1,234   NaN
x       NaN
1y      NaN
z2      NaN

Ответ или решение

Преобразование чисел в слова: создание скрипта на Bash для Linux

В задачи программиста часто входит необходимость представлять числовые значения в текстовом формате. В данном случае мы сосредоточимся на разработке скрипта на Bash, который будет конвертировать числа в слова на голландском языке. Данный проект имеет свою специфику, включая недостаток времени и игнорирование дробных значений.

Исходные ошибки и их исправления

Ваш исходный код содержит несколько ошибок, которые необходимо исправить:

  1. Неправильное использование переменных: Переменные в Bash необходимо объявлять без кавычек и необходимо избегать использования expr. Вместо этого используйте $(()).
  2. Неверные математические операции: Логика вычислений в ваших выражениях не совсем верна. Кроме того, необходимо правильно открывать и закрывать скобки.
  3. Использование -prijs: Этот элемент является частью вашей программы, но в текущем контексте он неправильно применяется. Следует использовать просто echo.

Обновленный код

Вот обновленный код, который исправляет вышеперечисленные ошибки и увеличивает ясность:

#!/bin/bash

echo "Введите цену: "
read price

# Вычисление разрядов
thousands=$((price / 1000))
hundreds=$((price % 1000 / 100))
teens=$((price % 100 / 10))
units=$((price % 10))

# Функция для преобразования чисел в слова
number_to_words() {
    local number=$1
    local words=""

    # Тысячи
    case $number in
        0) words="" ;;
        1) words="één" ;;
        2) words="twee" ;;
        3) words="drie" ;;
        4) words="vier" ;;
        5) words="vijf" ;;
        6) words="zes" ;;
        7) words="zeven" ;;
        8) words="acht" ;;
        9) words="negen" ;;
    esac

    # Добавьте множество разрядов аналогично
    # [...]

    echo $words
}

# Вывод преобразованных данных
echo "Цена в словах: "
echo "$(number_to_words $thousands) $(number_to_words $hundreds) $(number_to_words $teens) $(number_to_words $units)"

Обратите внимание, что функции и конструкция case проще настроить для выполнения всех необходимых преобразований. Для полноты реализации вы можете добавить дополнительные случаи для других разрядов (десятки, сотни и тысячи), придерживаясь аналогичной структуры, чтобы предоставить правильные финальные слова для всех частей числа.

Заключение

Создание скрипта для преобразования чисел в слова может значительно улучшить функциональность ваших приложений, особенно в области, где требуется читаемость финансовой информации. Исправление возможных ошибок синтаксиса и логики в коде является важным шагом. Внедряя предложенные изменения, вы сможете получить полностью рабочий скрипт, который точно передает числовые значения в текстовом формате. В дополнение к скрипту, вы также можете использовать утилиты от сторонних разработчиков, такие как spellout, для более сложных задач преобразования.

Надеюсь, это руководство помогло вам выявить и исправить ошибки в вашем коде, а также расширить ваши знания по работе со скриптами Bash.

Оцените материал
Добавить комментарий

Капча загружается...