jq — Selection

select — Filter Objects by Condition

Keep objects where a field matches a value
echo '[{"name":"eth0","state":"UP"},{"name":"lo","state":"UNKNOWN"},{"name":"wlan0","state":"DOWN"}]' | \
    jq '.[] | select(.state == "UP")'
# Output:
# {"name": "eth0", "state": "UP"}

select(condition) is jq’s WHERE clause. It passes through objects where the condition is truthy and silently drops the rest.

Select with numeric comparison
echo '[{"name":"eth0","mtu":1500},{"name":"lo","mtu":65536},{"name":"docker0","mtu":1500}]' | \
    jq '[.[] | select(.mtu > 1500)]'
# Output:
# [
#   {"name": "lo", "mtu": 65536}
# ]
Select with negation
echo '[{"name":"eth0","state":"UP"},{"name":"lo","state":"UNKNOWN"},{"name":"wlan0","state":"DOWN"}]' | \
    jq '[.[] | select(.state != "DOWN")]'
# Output:
# [
#   {"name": "eth0", "state": "UP"},
#   {"name": "lo", "state": "UNKNOWN"}
# ]

test — Regex Matching

Filter strings by regex pattern
echo '["eth0","wlan0","lo","docker0","br-abc123","veth456"]' | \
    jq '[.[] | select(test("^(eth|wlan)"))]'
# Output:
# ["eth0", "wlan0"]

test("pattern") returns true/false. Combine with select() to filter. Supports PCRE-like regex.

Case-insensitive regex
echo '["Error: timeout","WARNING: retry","error: connection refused","INFO: ok"]' | \
    jq '[.[] | select(test("error"; "i"))]'
# Output:
# ["Error: timeout", "error: connection refused"]

The second argument to test() is a flags string. "i" for case-insensitive, "x" for extended.

Filter objects by regex on a field
echo '[{"host":"web-01","ip":"10.0.1.10"},{"host":"db-01","ip":"10.0.2.20"},{"host":"web-02","ip":"10.0.1.11"}]' | \
    jq '[.[] | select(.host | test("^web"))]'
# Output:
# [
#   {"host": "web-01", "ip": "10.0.1.10"},
#   {"host": "web-02", "ip": "10.0.1.11"}
# ]

has — Check Key Existence

Keep objects that have a specific key
echo '[{"name":"eth0","ip":"10.0.0.1"},{"name":"lo"},{"name":"wlan0","ip":"10.0.0.2"}]' | \
    jq '[.[] | select(has("ip"))]'
# Output:
# [
#   {"name": "eth0", "ip": "10.0.0.1"},
#   {"name": "wlan0", "ip": "10.0.0.2"}
# ]

has("key") checks if the key exists at all — even if its value is null. Different from .key != null.

Check if array has an index
echo '[10,20,30]' | jq 'has(5)'
# Output: false

echo '[10,20,30]' | jq 'has(2)'
# Output: true

Type Checks

Filter by value type
echo '{"name":"eth0","mtu":1500,"active":true,"tags":["prod"],"meta":null}' | \
    jq '[to_entries[] | select(.value | type == "string") | .key]'
# Output:
# ["name"]
Dispatch based on type
echo '[1,"hello",true,null,[1,2],{"a":1}]' | \
    jq '.[] | "\(type): \(.)"'
# Output:
# "number: 1"
# "string: hello"
# "boolean: true"
# "null: null"
# "array: [1,2]"
# "object: {\"a\":1}"

Compound Conditions

AND — multiple conditions with and
echo '[{"name":"eth0","state":"UP","mtu":1500},{"name":"lo","state":"UNKNOWN","mtu":65536},{"name":"wlan0","state":"UP","mtu":1500}]' | \
    jq '[.[] | select(.state == "UP" and .mtu == 1500)]'
# Output:
# [
#   {"name": "eth0", "state": "UP", "mtu": 1500},
#   {"name": "wlan0", "state": "UP", "mtu": 1500}
# ]
OR — either condition
echo '[{"name":"eth0","state":"UP"},{"name":"lo","state":"UNKNOWN"},{"name":"wlan0","state":"DOWN"}]' | \
    jq '[.[] | select(.state == "UP" or .state == "UNKNOWN")]'
# Output:
# [
#   {"name": "eth0", "state": "UP"},
#   {"name": "lo", "state": "UNKNOWN"}
# ]
NOT — negate with not
echo '["eth0","wlan0","lo","docker0","veth123"]' | \
    jq '[.[] | select(test("^(docker|veth|br-)") | not)]'
# Output:
# ["eth0", "wlan0", "lo"]

contains and inside

Check if a string contains a substring
echo '"connection refused by remote host"' | jq 'contains("refused")'
# Output: true
Check if an array contains elements
echo '["ssh","http","https","dns"]' | jq 'contains(["ssh","dns"])'
# Output: true

contains checks for subset inclusion. For arrays, every element of the argument must appear in the input.

inside — reverse of contains
echo '["ssh"]' | jq 'inside(["ssh","http","dns"])'
# Output: true

any and all

Check if any element matches
echo '[{"name":"eth0","state":"UP"},{"name":"lo","state":"UNKNOWN"}]' | \
    jq 'any(.[]; .state == "DOWN")'
# Output: false
Check if all elements match
echo '[{"name":"eth0","mtu":1500},{"name":"wlan0","mtu":1500}]' | \
    jq 'all(.[]; .mtu == 1500)'
# Output: true

any(generator; condition) and all(generator; condition) are jq’s EXISTS and FORALL. The semicolon separates the generator (what to iterate) from the test (what to check).

indices and index

Find positions of matching elements
echo '["eth0","lo","wlan0","lo","docker0"]' | jq '[indices("lo")]'
# Output: [[1, 3]]
Find first occurrence
echo '"error: connection timeout at line 42"' | jq 'index("timeout")'
# Output: 21