Chapter 02Lesson 05~50 minutes

Integer Arithmetic, Strings, and Bash's Dynamic Data Model

Bash does not have the same static type system as languages such as Go, Java, or Rust. Most shell values behave as strings, while specific syntactic contexts interpret those values as integers. Knowing exactly when that interpretation occurs prevents subtle automation bugs.

BeginnerBash scriptingHands-on lab

Learning objectives

By the end of this lesson

  • Describe Bash's string-oriented variable model and attribute-based declarations.
  • Perform integer arithmetic with arithmetic expansion and arithmetic commands.
  • Distinguish string comparison from numeric comparison.
  • Use numeric bases and increments safely.
  • Recognize when Bash arithmetic is insufficient and another tool is more appropriate.

1. Bash variables are dynamically interpreted

A normal Bash variable does not carry a static type declaration that permanently fixes it as a string, integer, boolean, or object. Its text can be interpreted differently depending on context.

value=42
printf 'as text: %s\n' "$value"
printf 'as arithmetic: %s\n' "$(( value + 8 ))"

value="release-42"
printf 'now text: %s\n' "$value" 

Bash does support variable attributes through declare, including an integer attribute, arrays, readonly status, export status, and case conversion. These are shell semantics rather than a conventional static type system.

2. Arithmetic expansion produces a shell word

The form $(( expression )) evaluates integer arithmetic and substitutes the result into the surrounding command.

requests=120
workers=5

per_worker=$(( requests / workers ))
remainder=$(( requests % workers ))

printf 'per_worker=%d remainder=%d\n' "$per_worker" "$remainder" 
OperatorsPurposeNote
+, -, *, /Basic integer arithmeticDivision truncates fractional parts
%RemainderUseful for cycles and divisibility
**ExponentiationBash extension
<<, >>, &, |, ^Bitwise operationsUseful for masks and low-level values

3. (( ... )) is an arithmetic command with an exit status

Double parentheses without a leading dollar sign form an arithmetic command. Its exit status is zero when the resulting arithmetic value is non-zero and one when the value is zero.

count=3

if (( count > 0 )); then
  printf 'work is available\n'
fi

(( count-- ))
printf 'remaining=%d\n' "$count" 
Important edge case

Because (( expression )) reports failure when the arithmetic result is zero, increment/decrement expressions can interact unexpectedly with strict error handling. Learn the exit-status semantics before using them under set -e.

4. declare -i adds an integer attribute

An integer-attributed variable evaluates assigned values arithmetically.

declare -i retries=2
retries=retries+3
printf 'retries=%d\n' "$retries"

declare -p retries

This can be convenient, but it also means assignment semantics differ from ordinary string variables. Use the attribute when it makes the variable's role clearer rather than as a substitute for explicit validation.

5. String and numeric comparisons are different operations

The strings 10 and 2 have one lexical ordering, while the integers 10 and 2 have another numeric ordering.

a=10
b=2

if [[ $a < $b ]]; then
  printf 'string comparison: 10 sorts before 2\n'
fi

if (( a > b )); then
  printf 'numeric comparison: 10 is greater than 2\n'
fi

Inside [[ ... ]], < and > compare strings. Numeric tests can use arithmetic context (( ... )) or integer test operators such as -lt and -gt.

6. Arithmetic values can use explicit bases

Bash arithmetic can parse values using base#number notation.

binary=$(( 2#101101 ))
hex=$(( 16#ff ))
decimal=$(( 10#08 ))

printf 'binary=%d hex=%d decimal=%d\n' "$binary" "$hex" "$decimal" 

The explicit 10# form is sometimes useful when parsing zero-padded decimal strings. Without care, leading-zero notation can be interpreted in ways that surprise script authors.

7. Validate external numeric input before arithmetic

Arithmetic contexts are powerful enough that untrusted text should not be treated casually as an arithmetic expression. If a script expects decimal digits, validate that contract first.

value=${1:-}

if [[ ! $value =~ ^[0-9]+$ ]]; then
  printf 'error: expected a non-negative decimal integer\n' >&2
  exit 64
fi

printf 'next=%d\n' "$(( 10#$value + 1 ))" 
Input boundary

Treat command-line arguments, environment values, file contents, and API output as untrusted input until they have been validated for the syntax your script expects.

8. Know the limits of Bash arithmetic

Bash arithmetic is integer arithmetic based on the shell's supported integer representation. It is not a floating-point, arbitrary-precision, statistical, or decimal-finance engine.

Use another tool when the problem demands it:

  • awk for lightweight numeric text processing.
  • bc for calculator-style arbitrary precision where available.
  • Python for structured data, floating-point work, decimal arithmetic, date/time logic, or algorithms that have outgrown shell.
# Example: delegate floating-point work to awk.
awk 'BEGIN { printf "%.2f\n", 7 / 3 }' 

9. Strings remain the dominant shell data representation

Paths, command names, arguments, URLs, labels, JSON fragments, identifiers, and configuration usually enter Bash as text. Correct quoting is therefore central to Bash's data model.

artifact="release candidate.tar.gz"

printf 'safe single argument: <%s>\n' "$artifact"

# Compare argument counts.
bash -c 'printf "argc=%s\n" "$#"' _ "$artifact"
bash -c 'printf "argc=%s\n" "$#"' _ $artifact

The unquoted expansion undergoes word splitting and may become multiple arguments. This is why shell correctness often depends more on expansion and quoting semantics than on “types.”

10. Hands-on lab: calculate a deployment batch plan

Create a script that validates three integer inputs and calculates full batches plus any remainder.

mkdir -p "$HOME/devops-academy/bash/chapter02/lesson05"
cd "$HOME/devops-academy/bash/chapter02/lesson05"

cat > batches.sh <<'EOF'
#!/usr/bin/env bash

instances=${1:-}
batch_size=${2:-}
delay_seconds=${3:-}

for value in "$instances" "$batch_size" "$delay_seconds"; do
  if [[ ! $value =~ ^[0-9]+$ ]]; then
    printf 'usage: %s INSTANCES BATCH_SIZE DELAY_SECONDS\n' "$0" >&2
    exit 64
  fi
done

instances=$(( 10#$instances ))
batch_size=$(( 10#$batch_size ))
delay_seconds=$(( 10#$delay_seconds ))

if (( batch_size == 0 )); then
  printf 'error: BATCH_SIZE must be greater than zero\n' >&2
  exit 64
fi

full_batches=$(( instances / batch_size ))
remainder=$(( instances % batch_size ))
total_batches=$(( full_batches + (remainder > 0 ? 1 : 0) ))
minimum_delay=$(( total_batches > 0 ? (total_batches - 1) * delay_seconds : 0 ))

printf 'instances=%d\n' "$instances"
printf 'full_batches=%d\n' "$full_batches"
printf 'remainder=%d\n' "$remainder"
printf 'total_batches=%d\n' "$total_batches"
printf 'minimum_inter_batch_delay=%ds\n' "$minimum_delay"
EOF

bash batches.sh 23 5 30

Verification checklist

11. Knowledge check

Question 1. What is the difference between $((...)) and ((...))?

Question 2. Why can [[ 10 < 2 ]] be true?

Question 3. Is Bash the right tool for precise decimal financial arithmetic?

12. Summary

Bash is dynamically interpreted and overwhelmingly text-oriented. Arithmetic contexts temporarily interpret values as integers, while ordinary expansions continue to behave as shell words. The practical rules are straightforward: validate numeric input, choose numeric versus string comparisons deliberately, understand the exit status of arithmetic commands, and move complex numeric work to a more suitable language.

13. Further reading

  • GNU Bash Reference Manual — Shell Arithmetic and Bash Conditional Expressions.
  • POSIX arithmetic expansion specification.
  • ShellCheck documentation — arithmetic and numeric-input diagnostics.
  • GNU Awk documentation — numeric processing when shell arithmetic is insufficient.
Next lesson

stdin, stdout, stderr, and File Descriptors

Chapter 3 will move from shell data into standard streams, redirection, and production pipelines.

Keep the academy open

Support free, practical DevOps education.

Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.

Ethereum / ERC-20
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0 Send only Ethereum/ERC-20 compatible assets to this address.