Extract Functions
Most programming languages provide a way to enclose expressions within a function so that you can:
- use those expressions in multiple places without copying and pasting
- give expressions a name that makes them easier to refer to and easier to understand when you use them
You can do this in jq
using the keyword def
, which is shorthand for “define”.
A Realistic Example
I often want to capture parts of text using regular expressions, then turn them into an object. Here is what that looks like:
jq -n '"CAD 175.62" | capture("(?<currency>\\p{alpha}{3}) (?<value>[^\\p{space}]+)")'
{ "currency": "CAD", "value": "175.62"}
Extracting a Function
That capture()
expression (maybe) makes sense to you now, just after you wrote it, but that familiarity fades with time. You might prefer to extract a function for it.
jq -n '"CAD 175.62" | def parse_monetary_amount: capture("(?<currency>\\p{alpha}{3}) (?<value>[^\\p{space}]+)"); parse_monetary_amount'
{ "currency": "CAD", "value": "175.62"}
Good news, bad news. Good news: we’ve named this expression so that we can use it without needing to know exactly how it does its job; bad news: defining a function inline like this risks making the overall program harder to read, not easier. Since “main” is unmarked, how do you recognize where the entry point starts? I don’t find it particularly clear, do you?
Improve Formatting
Good news: we can use whitespace to make this code easier to skim.
jq -n '"CAD 175.62" | def parse_amount: capture("(?<currency>\\p{alpha}{3}) (?<value>[^\\p{space}]+)");
parse_amount'
{ "currency": "CAD", "value": "175.62"}
If you’re going to do that, however, you are probably ready to move this code into its own source code file. That comes next.