Skip to content

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:

Terminal window
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.

Terminal window
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.

Terminal window
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.