Validate email addresses with JQ

In this article i will show you a handy one-liner that can do the following, read from stdin a text file with email addresses, verify that…

Validate email addresses with JQ
Photo by César Ardila on Unsplash

In this article i will show you a handy one-liner that can do the following, read from stdin a text file with email addresses, verify that the addresses are valid, and finally generate JSON output with the results on stdout, JSON the to go format for APIs so, generating JSON output is a very nice to have knowledge!

The one-liner

Here is the one-liner which does all the job, might seem complicated but it isnt, i will explain everything you need to know!

cat emails.txt | jq -Rn '[inputs | {"email": ., "valid": (test("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$")?)}]'
  • emails.txt is the file that will contain the email addresses, here is an example content
john.doe@example.com 
invalid-email@ 
jane_smith123@domain.co.uk 
user@domain 
another.valid.email@sub.domain.com 
no-at-symbol.com 
valid.email@domain.org
  • jq -Rn -R processes input as raw strings and not JSON, each line is a separate string. -n this starts jq with a null input, allowing jq to create a JSON output.
  • [inputs | {…}] input is a filter which reads all the input lines from stdin, the outer brackets […] indicates that we create an array of objects.
  • {“email”: ., “valid”: …} generates the json object for each email that will check, value of valid will be generated by a “test” function that will verify with a regex if the address is valid or not.
  • test(…) contains our regex that verifies of the email is valid or not
  • ^[a-zA-Z0-9._%+-]+: Matches the beginning of the string with one or more allowed characters before the @ symbol.
  • @[a-zA-Z0-9.-]+: Matches the @ symbol followed by one or more allowed characters for the domain.
  • \\.: Matches a literal dot. The backslash \\ is used to escape the dot in the regex pattern.
  • [a-zA-Z]{2,}$: Matches the top-level domain which must have at least two characters.
  • ?: Ensures that test returns false instead of an error if the input does not match the regex.

Running the one-liner

Lets now execute the one-liner vs our email.txt file, we can see that generates a very nice and readable JSON output for each email

cat emails.txt | jq -Rn '[inputs | {"email": ., "valid": (test("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$")?)}]' 
 
[ 
  { 
    "email": "john.doe@example.com", 
    "valid": true 
  }, 
  { 
    "email": "invalid-email@", 
    "valid": false 
  }, 
... 
... 
...

Conclusion

jq is a powerful tool, is like grep for json files, it can do a lot of staff and is super useful when you want quickly to perform validations, in a next article i will provide an example on how to use inotify to trigger the execution of a script upon a file creation.