Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Loop JSON in Bash: How to Extract Variables?

Learn how to loop through a JSON file in bash and extract values into variables using jq. Perfect for automating config scripts.
Illustrated Bash terminal screen parsing JSON with jq, showing coding variables being extracted for scripting automation Illustrated Bash terminal screen parsing JSON with jq, showing coding variables being extracted for scripting automation
  • 🧰 Bash doesn't natively support JSON—it's best parsed using dedicated tools like jq.
  • 💡 jq -c simplifies JSON array iteration by outputting each object as one line.
  • 🔐 Using read with jq ensures safer variable assignment in Bash scripts.
  • ⚠️ The ? operator and // fallback in jq prevent crashes due to missing fields.
  • 🚀 JSON parsing in Bash is important for today's DevOps work and API connections.

Automating tasks through Bash scripting is powerful. But working with JSON data in shell scripts can be hard without the right tools. Whether you're getting API responses, parsing config files, or managing deployment settings, looping through JSON and getting values with tools like jq saves time and makes fewer mistakes. This guide shows you how to parse and change JSON data in Bash scripts using jq.


Bash Has No Native JSON Parser

The Bash shell wasn't made for parsing structured data formats like JSON. It can handle simple text changes using tools such as grep, awk, and sed. But these don't work well for JSON's nested setup and complex data. Even a small formatting difference—like spaces or special characters—can cause traditional Unix text tools to act strangely.

For example, look at this JSON:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

{
  "name": "Jane",
  "details": {
    "email": "jane@example.com",
    "roles": ["admin", "editor"]
  }
}

Getting values with sed or grep quickly becomes unreliable when the structure grows or changes. Because of this, you need a JSON-aware tool like jq.


Why Use jq for JSON in Bash?

jq is a command-line JSON processor made to filter, get, and change JSON data. Think of it as sed for JSON—but much stronger. It understands the JSON structure. This means it can reliably get to nested keys, arrays, and even use 'if-then' logic on data.

Advantages of jq

  • Lightweight and fast
  • Works on Linux, macOS, and Windows
  • Lets you build strong queries
  • Handles nested JSON and arrays easily
  • Puts out safe, predictable formatting (good for scripts)

Installing jq

To start using jq, install it with your system’s package manager:

# Debian/Ubuntu
sudo apt install jq

# macOS with Homebrew
brew install jq

# RedHat/CentOS
sudo yum install jq

# Windows (with Chocolatey)
choco install jq

Once installed, run jq --version to confirm it's working.


Basic jq Examples

Here are some basic ways to get comfortable with jq:

Get a single field

jq '.name' config.json

Get raw string (no quotes or escape characters)

jq -r '.name' config.json

Get nested field

jq -r '.details.email' config.json

Get array values

jq -r '.details.roles[]' config.json
jq '.' config.json

Reading JSON in Bash

Before parsing JSON, you usually read it into your script:

json=$(<config.json)

Good ways to do it:

  • Use $(<filename) instead of cat filename | to not use extra background processes.
  • Quote the variable when passing to jq, e.g., echo "$json" | jq to stop words from splitting.

Avoid:

cat config.json | jq '.name'  # Less efficient

Instead, use:

jq '.name' config.json  # More efficient

Using jq to Loop Through JSON Arrays in Bash

Looping through arrays is common. JSON lists often show groups like users, settings, or records.

Example JSON Array

{
  "users": [
    { "name": "Alice", "email": "alice@example.com" },
    { "name": "Bob", "email": "bob@example.com" }
  ]
}

Bash and jq Loop Pattern

for row in $(jq -c '.users[]' config.json); do
  name=$(echo "$row" | jq -r '.name')
  email=$(echo "$row" | jq -r '.email')
  echo "User $name with contact $email"
done

Key Notes:

  • -c sends out "compact" JSON: one object per line. Perfect for Bash loops.
  • Always quote $row when piping. It stops problems from special characters or line breaks.

This approach works well for short, well-structured JSON arrays. For larger or multiline data, while read loops or mapfile can work better.


Getting JSON Values into Variables

A strong way is using jq to define variables right within Bash:

name=$(jq -r '.user.name' config.json)

This quickly loads values for logic, logging, or passing into other tools.

Safer with read

To stop problems from new lines or encoding issues, use read:

read name <<< "$(jq -r '.user.name' config.json)"

You can even assign multiple values:

read name email <<< "$(jq -r '.user.name + " " + .user.email' config.json)"

Or use an array:

readarray -t roles < <(jq -r '.user.roles[]' config.json)

Now ${roles[0]}, etc., have each role in a clear way.


Parsing Nested JSON Structures in Bash

JSON isn’t flat—it often has many levels and arrays. Thankfully, jq gets to nested parts in a clear way.

Example Nested JSON

{
  "service": {
    "metadata": {
      "id": "svc123",
      "config": {
        "enabled": true,
        "thresholds": [10, 20, 30]
      }
    }
  }
}

Query Nested Value

jq -r '.service.metadata.config.enabled' config.json

Loop Over Nested Array

jq -r '.service.metadata.config.thresholds[]' config.json

Use jq -c if each array element is an object:

jq -c '.services[].config' config.json

You can chain these together to go many levels deep. This lets you combine filters, conditions, and array indexing.


Handle Errors and Missing Fields Gracefully

Missing or unexpected keys can break your script. jq has safe ways to find things:

Optional Field with ?

jq -r '.user?.email' config.json

This stops errors if the user object is not there.

Default/Fallback Values with //

jq -r '.user.name // "Unknown"' config.json

This gives a fallback if the name is null or missing.

Conditional with if Expression

jq -r 'if has("user") then .user.name else "N/A" end' config.json

You can put this logic into your scripts to replace missing info or react the right way.


Here’s where bash json loop, extract json values bash, and jq bash script ways are most helpful:

  1. CI/CD Pipelines
    Parse setup details from JSON for Docker, Kubernetes, or Terraform.

  2. API Connections
    Read outputs from REST APIs and start actions (e.g., send Slack alerts, record deployment states).

  3. Setup Management
    Load script options from JSON to control how it acts on the fly.

  4. Monitoring Scripts
    Parse data about system health from JSON to manage warning paths.


Avoid Bash Pitfalls with JSON Data

Don’t:

  • 🚫 Use eval to process JSON (security risk)
  • 🚫 Loop using for x in $(cat file) when data can contain line breaks
  • 🚫 Assume fields or array sizes—always check and test

Do:

  • ✅ Use jq -r to get raw strings
  • ✅ Quote variables passed to commands: echo "$json"
  • ✅ Test fallback paths for missing keys

These steps will make your scripts stronger and easier to keep up.


Real-Life Example: Parse API Response in Bash

Let’s work with live data from an external API (fake endpoint used here):

response=$(curl -s https://api.example.com/data)

Get Values in a Loop

for row in $(echo "$response" | jq -c '.results[]'); do
  id=$(echo "$row" | jq -r '.id')
  status=$(echo "$row" | jq -r '.status')
  echo "Item $id has status $status"
done

This works well when you watch logs, work with data from others, or react to live events using webhooks.


Reusable Bash Functions for JSON Parsing

Change your code to use helper functions:

extract_value() {
  local path=$1
  local file=$2
  jq -r "$path" "$file"
}

user_id=$(extract_value '.user.id' config.json)

For more complex logic:

extract_nested_array() {
  jq -r "$1[]" "$2"
}

extract_nested_array '.service.metadata.config.thresholds' config.json

Functions mean less copying and pasting. They also make fixing problems easier.


Speed Up with jq Shortcuts and Aliases

Make your work better with these Bash aliases:

alias jqp="jq '.' | less"
alias jql="jq -r"

Create Inline CLI Tools

#!/bin/bash
# jsongrep.sh
jq -r ".$1" "$2"

Invoke as:

./jsongrep.sh user.name config.json

When you mix Bash's simplicity with jq's flexibility, you get strong development tools fast.


When to Move Beyond Bash for JSON

Bash has limits—especially with very nested, big, or changing data setups. Then, you should switch to:

  • Python: Has full parsing with its json module—great for strong tools.
  • Node.js: Parses data based on events with easy rules.
  • Go/Rust: Fast tools for handling JSON in live systems.

But for small to medium automation, jq and Bash scripts work very well.


Final Takeaways

Learning how to use bash json loop and get values with jq opens up many ways to automate tasks. This goes from local scripts to live system setups. Whether you're working with API outputs, setup lists, or nested objects, jq helps Bash work smoothly with JSON.

  • Stick to jq for safe, reliable parsing
  • Use read and jq -r to manage values in variables
  • Loop through arrays in a clear way using -c and quoted inputs
  • Check input JSON before you work with it
  • Think about changing languages if things get too hard

With these skills, you can make scripting easier across CI pipelines, APIs, DevOps tools, and more—you won't need other programming languages.


Citations

Travers, N. (2022). Why jq is the universal JSON CLI tool for developers. Linux Journal. Retrieved from https://linuxjournal.com

Stack Overflow Developer Survey. (2023). Most commonly used tools among developers. StackOverflow Insights. Retrieved from https://insights.stackoverflow.com

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading