Transform text from the command-line using Haskell expressions.


Version on this page:
LTS Haskell 19.33:
Stackage Nightly 2022-03-17:
Latest on Hackage:

See all snapshots haskell-awk appears in

Apache-2.0 licensed by Mario Pastorelli, Samuel Gélineau
This version can be pinned in stack with:haskell-awk-,6534

Module documentation for

Hawk Hackage Build Status

Transform text from the command-line using Haskell expressions. Similar to awk, but using Haskell as the text-processing language.


In Unix the file /etc/passwd is used to keep track of every registered user in the system. Each entry in the file contains information about a single user, using a simple colon-separated format. For example:


The first field is the username. We can use Hawk to list all usernames as follows:

> cat /etc/passwd | hawk -d: -m 'head'

The -d option tells Hawk to use : as field delimiters, causing the first line to be interpreted as ["root", "x", "0", "0", "root", "/root", "/bin/bash"]. The -m tells Hawk to map a function over each line of the input. In this case, the function head extracts the first field of the line, which happens to be the username.

We could of course have achieved identical results by using awk instead of Hawk:

> cat /etc/passwd | awk -F: '{print $1}'

While Hawk and awk have similar use cases, the philosophy behind the two is very different. Awk uses a specialized language designed to concisely express many text transformations, while Hawk uses the general-purpose language Haskell, which is also known for being concise, among other things. There are many standard command-line tools that can be easily approximated using short Haskell expressions.

Another important difference is that while awk one-liners are self-contained, Hawk encourages the use of libraries and user-defined functions. By adding function definitions, module imports and language pragmas to Hawk’s user-configurable prelude file, those functions, libraries and language extensions become available to Hawk one-liners. For instance, we could add a takeLast function extracting the last n elements from a list, and use it to (inefficiently) approximate tail:

> echo 'takeLast n = reverse . take n . reverse' >> ~/.hawk/prelude.hs
> seq 0 100 | hawk -a 'takeLast 3'

For more details, see the presentation and the documentation.


To install hawk, either run stack install haskell-awk or cabal install haskell-awk.

You should be ready to use Hawk:

> hawk '[1..3]'

The first run will create a default configuration file into ~/.hawk/prelude.hs if it doesn’t exist.


What’s new?

New in

  • support ghc-8.6 again and back to ghc-8.0 (Stackage LTS 9)
  • fix missing test files in released tarball (#257)

New in 1.2

  • Added support for ghc-9.0.1, ghc-8.10 and ghc-8.8, dropped support for ghc-8.6 and below.
  • Drop support for Windows. Please contact us if you would like us to re-enable it.
  • Error messages use the correct column number.
  • The flag -d without an argument no longer implies -o without an argument. That is, when using whitespace to delimit words in the input, we now also use whitespace to delimit words in the output, we no longer use the empty string as a delimiter.
  • Hawk can now be installed using either stack, cabal-v1, cabal-v2, or cabal-sandbox.
  • Hawk no longer suspiciously opens a port; we now use files for locking, not a unix socket.

New in 1.1.1

GHC 7.10 compatibility.

New in 1.1

In a nutshell, custom context directories and GHC 7.8 compatibility.

Breaking changes

  • The detection of whether the user prelude needs to be recompiled has been improved, leading to the removal of the no-longer useful --recompile flag.

“Breaking” changes (if you used internal stuff)

  • The haskell-awk library has changed.
  • The format of ~/.hawk/cache has changed.

New features

  • GHC 7.8 compatibility.
  • A context directory other than ~/.hawk can be specified.
  • A .hawk directory can be placed in the current directory (or one of its ancestors) and it will be used instead of ~/.hawk. This allows different projects to use different user preludes.


  • Some examples from the documentation needed minor changes in order to produce the documented output.
  • hawk "" is now a syntax error.
  • cabal install --enable-tests no longer complains that the runtime isn’t installed.

Minor improvements

  • The nomenclature for “lines” and “words” is now “records” and “fields”, because the delimiters don’t need to be newline and space.
  • Usage is shown when hawk is called with no arguments.
  • A warning message is displayed when ~/.hawk is first created.
  • More succinct --help output.
  • More uniform presentation of warnings and error messages.