Practical jq/yq/csvkit patterns for agents extracting, filtering, and reshaping JSON/YAML/CSV in shell pipelines. Triggers on: parse this JSON, extract from API output, convert CSV to JSON, reshape YAML, wrangle shell data.
./install.sh jq-yq-data-wranglingname: "jq_yq_data_wrangling" description: "Practical jq/yq/csvkit patterns for agents extracting, filtering, and reshaping JSON/YAML/CSV in shell pipelines. Triggers on: parse this JSON, extract from API output, convert CSV to JSON, reshape YAML, wrangle shell data." metadata: { "includeInPrompt": true }
Extract, filter, and reshape structured data (JSON, YAML, CSV) inside shell pipelines without round-tripping through Python or a browser. Covers jq for JSON, mikefarah yq for YAML, and csvkit for CSV. This skill is about structured-data extraction from APIs, files, and command output — not text scraping (that's web-research / log-forensics territory).
Default tooling choice: jq for JSON, mikefarah yq (eval subcommand, v4.x style) for YAML, csvkit for CSV. Set export PATH=$HOME/.local/bin:$PATH first so the user-local pip installs resolve.
jq essentials (wrap the filter in single quotes):
jq '.a.b'jq -r '.name'jq -c '.'jq '[.[] | {val: .v}]' (each .[] is one element)jq '[.[] | select(.v > 2)]'jq '[.[] | select(test("^a"))]'jq -r '.[] | "\(.n)=\(.v)"' → a=1 per linejq '.a?.b' (safe navigation), jq '.a // "default"' (fallback)jq -s '.'jq 'length', jq 'keys', jq 'sort_by(.v)'--arg, not string interpolation: jq --arg n "$NAME" -r '"hello \($n)"'jq -r '[.login, .id] | @csv'yq — know which one you have. Two flavors exist: mikefarah's Go yq (v4.x, the default here — it has an eval subcommand and handles YAML/JSON/TOML) and kislyuk's python yq (a jq wrapper; needs -y to emit YAML). If yq eval '.a.b' file.yaml errors, you're on python yq — add -y, or prefer the mikefarah binary.
yq eval '.a.b' file.yaml — pull a nested valueyq eval '.list[]' file.yaml — stream array elements, one per lineyq eval -o=json '.' file.yaml — convert YAML to JSON (then pipe to jq)yq eval '.a.b = "new"' -i file.yaml — edit a file in placecsvkit (column names are case-sensitive; CRLF input is handled automatically):
csvcut -c city,name data.csvcsvgrep -c city -m nyc data.csvcsvsort -c age data.csv (add -r for descending)csvlook data.csv (pretty aligned table)csvjson -i 4 data.csv (indent 4; -i sets indent)csvstat --csv data.csv (types, min/max, unique counts)csvjoin -c name a.csv b.csvcsvformat with the right terminator flag handles it.Common pipeline pattern: API response → jq → downstream CSV work:
bash
curl -s "https://api.github.com/users/octocat" \
| jq -r '[.login, .id, .public_repos] | @csv' \
| { echo "login,id,repos"; cat; } > out.csv
csvlook out.csv
--help or a local run.$ and !; jq ".a" will break. The only correct exception is deliberate single-quote wrapping around --arg-injected variables.--arg / --argjson for variables. Never interpolate shell variables into a jq filter string — it's brittle and an injection risk. jq --arg n "$NAME" '.items[] | select(.name == $n)'.-r when the output is text. Forgetting it returns "quoted" strings that break downstream string comparisons and file writes.csvcut -c Name fails when the header is name. When unsure, run csvcut -n data.csv first to list headers.csvformat only after the plain command visibly mis-parses.cmd --help before scripting a new flag" beats "never guess flags". State the reason, not a commandment.publisher key 2e43c913833850e6d80f939677e3de76e806d47785c0f1caaca90f9d18c98e1e
No ratings yet — be the first to rate it.