fixgrep Man Page

What is fixgrep

fixgrep is a command line utility for making FIX protocol messages more readable.

fixgrep features:

Some introductory examples

Horizontal format:

[MsgType]35=D[NEWORDERSINGLE]|[ClOrdID]11=C28|[Symbol]55=AUD/USD|[Side]54=2[SELL]|[OrderQty]38=1464820|[Price]44=100.026
[MsgType]35=8[EXECUTIONREPORT]|[ClOrdID]11=C28|[ExecType]150=0[NEW]|[LeavesQty]151=1464820|[CumQty]14=0|[Price]44=100.02
[MsgType]35=G[ORDERCANCELREPLACEREQUEST]|[ClOrdID]11=C32|[OrderQty]38=1465320|[OrdType]40=2[LIMIT]|[Price]44=100.12
[MsgType]35=8[EXECUTIONREPORT]|[ClOrdID]11=C32|[ExecType]150=5[REPLACED]|[LeavesQty]151=1465320|[CumQty]14=0|[Price]44=100.12
[MsgType]35=8[EXECUTIONREPORT]|[ClOrdID]11=C32|[ExecType]150=F[FILL]|[LeavesQty]151=1072490|[CumQty]14=392830|[Price]44=100.00

Vertical format (aligned):

================================================================================
NewOrderSingle
================================================================================
MsgType35=DNEWORDERSINGLE
ClOrdID11=C28
Symbol55=AUD/USD
Side54=2SELL
OrderQty38=1464820
Price44=100.026

================================================================================
Exec.New
================================================================================
MsgType35=8EXECUTIONREPORT
ClOrdID11=C28
ExecType150=0NEW
LeavesQty151=1464820
CumQty14=0
Price44=100.02

Vertical format (non-aligned):

================================================================================
MarketDataIncrementalRefresh
================================================================================
[MsgType]35=X[MARKETDATAINCREMENTALREFRESH]
[MDReqID]262=ABCD
[NoMDEntries]268=3
1.
[MDUpdateAction]279=0[NEW]
[MDEntryType]269=0[BID]
[Symbol]55=AUD/USD
[MDEntryPx]270=1.12345
2.
[MDUpdateAction]279=0[NEW]
[MDEntryType]269=1[OFFER]
[Symbol]55=AUD/USD
[MDEntryPx]270=1.12355
3.
[MDUpdateAction]279=0[NEW]
[MDEntryType]269=1[OFFER]
[Symbol]55=AUD/USD
[MDEntryPx]270=1.12355
[MDFeedType]1022=FeedA

Grouped by order:

=================================================================================
ORDER orderId:ABC clOrdId:C123
================================================================================
[MsgType]35=D[NEWORDERSINGLE]|[ClOrdID]11=C123|[Symbol]55=AUD/USD|[Side]54=2[SELL]|[OrderQty]38=269440|[OrdType]40=2[LIMIT]|[Price]44=99.98
[MsgType]35=8[EXECUTIONREPORT]|[OrderID]37=ABC|[ClOrdID]11=C123|[OrigClOrdID]41=C123|[Symbol]55=AUD/USD|[Side]54=2[SELL]|[ExecType]150=0[NEW]|[LeavesQty]151=269440|[Price]44=99.98
[MsgType]35=8[EXECUTIONREPORT]|[OrderID]37=ABC|[ClOrdID]11=C123|[OrigClOrdID]41=C123|[Symbol]55=AUD/USD|[Side]54=2[SELL]|[ExecType]150=F[FILL]|[LeavesQty]151=142770|[LastQty]32=126670|[Price]44=99.98
[MsgType]35=8[EXECUTIONREPORT]|[OrderID]37=ABC|[ClOrdID]11=C123|[OrigClOrdID]41=C123|[Symbol]55=AUD/USD|[Side]54=2[SELL]|[ExecType]150=F[FILL]|[LeavesQty]151=0|[LastQty]32=142770|[Price]44=99.98

=================================================================================
ORDER orderId:DEF clOrdId:C456
================================================================================
[MsgType]35=D[NEWORDERSINGLE]|[ClOrdID]11=C456|[Symbol]55=AUD/USD|[Side]54=1[BUY]|[OrderQty]38=902070|[OrdType]40=2[LIMIT]|[Price]44=99.98
[MsgType]35=8[EXECUTIONREPORT]|[OrderID]37=DEF|[ClOrdID]11=C456|[OrigClOrdID]41=C456|[Symbol]55=AUD/USD|[Side]54=1[BUY]|[ExecType]150=0[NEW]|[LeavesQty]151=902070|[Price]44=99.98
[MsgType]35=G[ORDERCANCELREPLACEREQUEST]|[OrigClOrdID]41=C456|[ClOrdID]11=C789|[Symbol]55=AUD/USD|[Side]54=1[BUY]|[OrderQty]38=902870|[OrdType]40=2[LIMIT]|[Price]44=99.88
[MsgType]35=8[EXECUTIONREPORT]|[OrderID]37=DEF|[ClOrdID]11=C789|[OrigClOrdID]41=C456|[Symbol]55=AUD/USD|[Side]54=1[BUY]|[ExecType]150=5[REPLACED]|[LeavesQty]151=902870|[Price]44=99.88
[MsgType]35=8[EXECUTIONREPORT]|[OrderID]37=DEF|[ClOrdID]11=C789|[OrigClOrdID]41=C456|[Symbol]55=AUD/USD|[Side]54=1[BUY]|[ExecType]150=F[FILL]|[LeavesQty]151=0|[LastQty]32=902870|[Price]44=99.88

How to get

Download the latest version from here
GitHub project can be found here

How to install

How to get help

How to run

There is a bash script file 'fixgrep' which should be your main interface to fixgrep. There are two ways to send fix data into fixgrep. The first is 'piping' e.g.
grep 11=ABC my-large-file.fix | fixgrep [options]
The second is specifying a file argument at the end of the fixgrep command. e.g.
fixgrep [options] my-file.fix
Note, fixgrep does not curently support wildcards to specify multiple files.

Ways to configure fixgrep

Fixgrep can be configured via three methods.

Differences between command-line options, and properties configuration

Command-line options (usually) provide at least two different options which configure the same parameter. Usually a short single character option, and a more descriptive option. e.g. -o, --output-delimiter both configure the output delimiter. However when configuring via the properties file only one option is available to use. That is the longest command-line option, with dashes replaced with dots. e.g. to configure the output delimiter in the properties file, you would need to use output.delimiter option. e.g. output.delimiter=| Below is a table listing the command line options, and on the right the equivalent properties to use in properties file configuration.
option variationsequivalent properties key
-A,--align-vertical-columns,--alignalign.vertical.columns
-D,--output-delimiter,--output-delimoutput.delimiter
-G,--suppress-indent-group-repeatssuppress.indent.group.repeats
-O,--group-by-ordergroup.by.order
-V,--vertical-formatvertical.format
-a,--tag-annotationstag.annotations
-d,--input-delimiter,--input-deliminput.delimiter
--download-urldownload.url
-e,--exclude-tagsexclude.tags
--fix-spec-path,--fix-specfix.spec.path
-g,--line-regexgroup-for-fixline.regexgroup.for.fix
-h,--highlights,--highlighthighlights
-m,--include-only-messages-of-typeinclude.only.messages.of.type
-n,--suppress-colors,--no-colorsuppress.colors
-o,--group-by-orders-with-idgroup.by.orders.with.id
--online-help-urlonline.help.url
--output-format-grouped-order-header-consoleoutput.format.grouped.order.header.console
--output-format-grouped-order-header-htmloutput.format.grouped.order.header.html
--output-format-horizontal-consoleoutput.format.horizontal.console
--output-format-horizontal-htmloutput.format.horizontal.html
--output-format-vertical-consoleoutput.format.vertical.console
--output-format-vertical-htmloutput.format.vertical.html
-q,--suppress-bold-tags-and-valuessuppress.bold.tags.and.values
-r,--input-line-formatinput.line.format
-s,--sort-by-tagssort.by.tags
-t,--only-include-tagsonly.include.tags
-v,--exclude-messages-of-typeexclude.messages.of.type
--vcs-home-urlvcs.home.url

Options

-a,--tag-annotations

Defines the format of annotations to use when printing fields.
Example usage:
fixgrep -a ba
Using the built in fix spec it is possible to annotate fix tags with information to make them more human readable. e.g. the fix message '35=D^A11=ABC^A55=AUD/USD' can be made much more readable when presented with the tag and/or value descriptions. e.g. '[MsgType] 35=D [NEWORDERSINGLE]|[ClOrdID] 11=ABC |[Symbol] 55=AUD/USD '. The default format is called 'outsideAnnotated' which means that the annotations sit on the outside of the tag=value pair. e.g. [tagAnnotation]tag=value[valueAnnotation].
Specified using this method, these are the possible option values:
formatexample
outsideAnnotated[MsgType]35=D[NEWORDERSINGLE]
insideAnnotated35[MsgType]=[NEWORDERSINGLE]D
replacedMsgType=NEWORDERSINGLE
none35=D
You can also specify the annotation format using codes. The first code for the tag annotation position, the second code for the value annotation position. Or, just specify one code to apply to both the tag and value annotation positions. Codes are:
codedescription
bAnnotation will appear BEFORE the tag or value
aAnnotation will appear AFTER the tag or value
rAnnotation will REPLACE the tag or value
_No annotation will be displayed
Any combination of 'b','a','r','_' is valid.
Examples:
codesexample
ba[MsgType]35=D[NEWORDERSINGLE]
ab35[MsgType]=[NEWORDERSINGLE]D
bb[MsgType]35=[NEWORDERSINGLE]D
b[MsgType]35=[NEWORDERSINGLE]D
aa35[MsgType]=D[NEWORDERSINGLE]
a35[MsgType]=D[NEWORDERSINGLE]
a_35[MsgType]=D
_a35=D[NEWORDERSINGLE]
b_[MsgType]35=D
_b35=[NEWORDERSINGLE]D
rrMsgType=NEWORDERSINGLE
rMsgType=NEWORDERSINGLE
r_MsgType=D
__35=D
none35=D

-A,--align-vertical-columns,--align

Aligns tags, values and annotations when viewing messages in vertical format.

-d,--input-delimiter,--input-delim

Defines the fix delimiter used in the input fix messages. Default to control character 1, i.e. \u0001
Example usage:
fixgrep -d :

-D,--output-delimiter,--output-delim

Defines the delimiter to print between fix tags in the formatted output.
Example usage:
fixgrep -D ;

-e,--exclude-tags

Tags to exclude from the formatted fix.
Example usage:
fixgrep -e 22,33
A comma separated list of tags which should not be displayed in the output 'formatted' fix. e.g. '--exclude-tags 22,33' would hide tags 22 and 33 from being displayed. Can be useful for hiding some of the less 'interesting' fix fields, such as BeginString, BodyLength or Checksum. Yawn!

-f,--to-file

Send output to a file with a generated filename. Filename is printed to std out after being written..
A random file will be generated, with the prefix 'fixgrep-'. And an extension of '.log' or '.html'.

-F,--to-given-file

Send output to a given file.
Example usage:
fixgrep -F output.txt
Output is printed to the specified file.

-o,--group-by-orders-with-id

Group order messages by orderId and/or clientOrderId which have an id containing the given text/regex expressions.
Example usage:
fixgrep -o abc,def\d\d\d
Using this option changes the 'mode' of fixgrep to discard any non-order messages, and to group the messages by order. fixgrep will attempt to keep track of 'order chains' when amends and cancels change the clOrdId, even if the orderId is not present on every message. Using this option can increase the memory used by fixgrep, as fixgrep will need to cache all order messages before printing them out. Even if order messages do not have ids which match the given expression(s), fixgrep still needs to cache them in case it discovers an amend or cancel in the order chain which DOES contain a match. Because fixgrep memory is limited to 128MG fixgrep _might_ stop with an OutOfMemoryException if it uses all of it's allocated heap. During matching; clientId, origClientId & orderId are scanned for text that contains the given expression(s) either literally, or as a regex.

-O,--group-by-order

Group order messages by orderId and/or clientOrderId.
Using this option changes the 'mode' of fixgrep to discard any non-order messages, and to group the messages by order. fixgrep will attempt to keep track of 'order chains' when amends and cancels change the clOrdId, even if the orderId is not present on every message. Using this option can increase the memory used by fixgrep, as fixgrep will need to cache all order messages before printing them out. This should not affect other processes on the box, but it might mean that fixgrep will stop with an OutOfMemoryException if it uses all of it's allocated heap.

-h,--highlights,--highlight

Highlight fields or lines using color or console text effects.
Example usage:
fixgrep -h 35,55
Format: criteria[:texteffect1][:texteffect2][:scope] (criteria is mandatory, texteffect and scope are optional.)

criteria

must start with a tag number, and can optionally have an equals or tilda followed by a string to match the tagsInId value against. An equals sign '=' performs an exact match. If just the tag number is specified, the tag and associated value will be highlighted. Multiple tag (and optional equals value) pairs can be chained together into an 'and' statement using the && operator. 'Or' statements are not supported as of yet, as you can just specify another highlight.

texteffect1 & texteffect2

are optional. It uses ansi escape codes to print display attributes which affect how the text is displayed. If this is not specified, fixgrep will loop through a predefined set of foreground colors. If specified, it can be of four different formats. 16 color text effects, 256 color text effects, Bold, or a raw escape code. Whether these escape codes will work will depend on your particular shell environment.

scope

is optional, and can be either 'Field' or 'Line', which controls whether just the field is highlighted, or the whole line. If not specified, just the Field is highlighted.'

Specifying texteffects

  • Defaults - If no texteffect is specified, then default colors are used. Fixgrep will loop through a predefined set of foreground colors. Those being: FgRed, FgGreen, FgYellow, FgBlue, FgPurple, FgCyan
  • 16-color text effects - comprise of the ansi 8 colors, and 8 'bright' colors, used as either a foreground text color, or a background color. You can specify these by using the format [Fg|Bg][Color]. e.g. foreground colors: FgBlackFgRedFgGreenFgYellowFgBlueFgPurpleFgCyanFgWhiteFgGrayFgBrightRedFgBrightGreenFgBrightYellowFgBrightBlueFgBrightMagentaFgBrightCyanFgBrightWhite and background colors: BgBlackBgRedBgGreenBgYellowBgBlueBgPurpleBgCyanBgWhiteBgGrayBgBrightRedBgBrightGreenBgBrightYellowBgBrightBlueBgBrightMagentaBgBrightCyanBgBrightWhite
  • 256-color text effects - You can see a 256 color palette by running 'fixgrep --256-color-demo' (This will also test if your console supports 256 colors.) Of if you're viewing the online man page, you should be able to see the palette listed under the --256-color-demo help section. To use colors from the 256 color palette, specify these using the format [Fg|Bg][num]. e.g. Fg5, Fg23, Bg107, Bg58
  • Raw Escape Codes - Allows you to specify whatever codes you want. e.g. RGB colors in the format\u001B[38;2;r;g;bm (where r,g,b are the numeric RGB values.) As long as the texteffect string starts with the escape code followed by a left square bracket, fixgrep will assume you are using a raw escape code.

Example highlights:

expressionmessage
-h 35
[MsgType]35=D[NEWORDERSINGLE]|[ClOrdID]11=ABC|[Symbol]55=AUD/USD
-h 35:Bold
[MsgType]35=D[NEWORDERSINGLE]|[ClOrdID]11=ABC|[Symbol]55=AUD/USD
-h 35:Bold:Msg
[MsgType]35=D[NEWORDERSINGLE]|[ClOrdID]11=ABC|[Symbol]55=AUD/USD
-h 11
[MsgType]35=D[NEWORDERSINGLE]|[ClOrdID]11=ABC|[Symbol]55=AUD/USD
-h 11:FgWhite:BgBlue
[MsgType]35=D[NEWORDERSINGLE]|[ClOrdID]11=ABC|[Symbol]55=AUD/USD
-h 11:FgWhite:BgBlue:Field
[MsgType]35=D[NEWORDERSINGLE]|[ClOrdID]11=ABC|[Symbol]55=AUD/USD
-h 11:FgWhite:BgBlue:Msg
[MsgType]35=D[NEWORDERSINGLE]|[ClOrdID]11=ABC|[Symbol]55=AUD/USD
-h 11:Field
[MsgType]35=D[NEWORDERSINGLE]|[ClOrdID]11=ABC|[Symbol]55=AUD/USD
-h 11:Msg
[MsgType]35=D[NEWORDERSINGLE]|[ClOrdID]11=ABC|[Symbol]55=AUD/USD
-h 35=D
[MsgType]35=D[NEWORDERSINGLE]|[ClOrdID]11=ABC|[Symbol]55=AUD/USD
-h 35=D:BgBlue:FgWhite
[MsgType]35=D[NEWORDERSINGLE]|[ClOrdID]11=ABC|[Symbol]55=AUD/USD
-h 35=D:Fg176
[MsgType]35=D[NEWORDERSINGLE]|[ClOrdID]11=ABC|[Symbol]55=AUD/USD
-h 35=D:Fg177:Msg
[MsgType]35=D[NEWORDERSINGLE]|[ClOrdID]11=ABC|[Symbol]55=AUD/USD
-h 35=D&&55=AUD
[MsgType]35=D[NEWORDERSINGLE]|[ClOrdID]11=ABC|[Symbol]55=AUD/USD
-h 35=D&&55=AUD:FgRed
[MsgType]35=D[NEWORDERSINGLE]|[ClOrdID]11=ABC|[Symbol]55=AUD/USD
-h 35=D&&55=AUD:FgRed:Field
[MsgType]35=D[NEWORDERSINGLE]|[ClOrdID]11=ABC|[Symbol]55=AUD/USD
-h 35=D&&55=AUD:FgRed:Msg
[MsgType]35=D[NEWORDERSINGLE]|[ClOrdID]11=ABC|[Symbol]55=AUD/USD
-h 35=D&&55=AUD&&11=AB:FgPurple
[MsgType]35=D[NEWORDERSINGLE]|[ClOrdID]11=ABC|[Symbol]55=AUD/USD

Some examples specifying multiple highlights (separated by commas):

expressionmessage
-h 35,55
[MsgType]35=D[NEWORDERSINGLE]|[ClOrdID]11=ABC|[Symbol]55=AUD/USD
-h 35=D,55=AUD
[MsgType]35=D[NEWORDERSINGLE]|[ClOrdID]11=ABC|[Symbol]55=AUD/USD
-h 35=D,55=XYZ
[MsgType]35=D[NEWORDERSINGLE]|[ClOrdID]11=ABC|[Symbol]55=AUD/USD
-h 35,55,11
[MsgType]35=D[NEWORDERSINGLE]|[ClOrdID]11=ABC|[Symbol]55=AUD/USD
-h 35:Bold,55
[MsgType]35=D[NEWORDERSINGLE]|[ClOrdID]11=ABC|[Symbol]55=AUD/USD
-h 35=D:Fg176,55=AUD&&11=AB:FgBlue:BgBrightYellow
[MsgType]35=D[NEWORDERSINGLE]|[ClOrdID]11=ABC|[Symbol]55=AUD/USD
-h 35=D:Fg176:Msg,55=AUD:BgBrightGreen
[MsgType]35=D[NEWORDERSINGLE]|[ClOrdID]11=ABC|[Symbol]55=AUD/USD

--output-format-horizontal-console

The format of each message when displaying fix on the console in horizontal format.
Example usage:
fixgrep --output-format-horizontal-console Thread:$1 ${msgFix}
See the section on 'Output Formatting' for more information.

--output-format-vertical-console

The format of each message when displaying fix in html in horizontal format.
Example usage:
fixgrep --output-format-vertical-console ==========\n${msgColor}${msgTypeName}${colorReset}\n==========\n${msgFix}
See the section on 'Output Formatting' for more information.

--output-format-horizontal-html

The format of each message when displaying fix on the console in horizontal format.
Example usage:
fixgrep --output-format-horizontal-html Thread:$1 ${msgFix}
See the section on 'Output Formatting' for more information.

--output-format-vertical-html

The format of each line when displaying fix on the console in horizontal format.
Example usage:
fixgrep --output-format-vertical-html
\n==========
\n${msgColor}${msgTypeName}${colorReset}
\n==========\n
\n${msgFix}\n
See the section on 'Output Formatting' for more information.

-g,--line-regexgroup-for-fix

Combined with the 'input-line-format' parameter, is used to specify which 'capturing group' of the regex contains the actual fix message.
Example usage:
fixgrep -g 2

--install

Create a customizable application.properties file in the ~/.fixgrep directory
Fixgrep will try to create a folder in the users home directory called '.fixgrep', and inside that folder fixgrep will try to create an application.properties file that the user can customize.

-l,--launch-browser

Will launch a browser containing the output log file.
Will open the output file in the system browser. Can only be used if the -f or --to-file option has been given.

-m,--include-only-messages-of-type

A comma separated list of msg types to display.
Example usage:
fixgrep -m D,8
e.g. to display only NewOrderSingles and ExecutionReports, use 35,8

-n,--suppress-colors,--no-color

Suppresses any colorization in lines.
Example usage:
fixgrep -n true
Note, see the 'suppress-bold-tags-and-values' parameter to also suppress usage of bold text effect on formatted lines

-q,--suppress-bold-tags-and-values

Suppresses the bold formatting of tags and values.
Example usage:
fixgrep -q true
By default tags and values are displayed in bold. E.g.: '[MsgType] 35=D [NEWORDERSINGLE]|[ClOrdID] 11=ABC [Symbol] 55=AUD/USD . In some shells highlighting and bold text don't work well together resulting in partially highlighted fields and lines. On such shells the user may wish to suppress bold tags and values, so that highlighting is not broken.

-r,--input-line-format

Defines the regex to use, when parsing input lines.
Example usage:
fixgrep -r \d\d\d\d-\d\d-\d\d \[(\d)\] (\d+=.*)
Although fix messages appear in some logs as 'pure' fix, they can also be displayed as part of an application's normal logging, and may have text appearing before/after the fix message (such as timestamps, thread identifiers, etc.) This pattern can be customized for your application so that fixgrep knows where to find the actual fix message in each log line. ^(\d{4}-[01]\d-[0-3]\d[T\s][0-2]\d:[0-5]\d:[0-5]\d[\.,]\d+)?.*?(\d+=.*$) , which looks for an optional ISO timestamp followed by any characters, followed by any number of tag=value pairs which make up the fix message.
This option can be used in conjunction with the parameter 'line-regexgroup-for-fix' to tell fixgrep, which regex 'group' to use. The default value for this is In the example above, the regex 'group' that contains the fix message is number 2, as the second set of capturing brackets (\d+=.*$) is where we'd expect to find the fix tag. This default format should match against most variations of fix logging formats, however you might want to modify it if there is any additional information that you wish to 'capture' and print back out by modifying the line=format parameter, and specifying $n tokens. Or if you wish to optimize the searching. For example, if your logs contain just fix messages (no other text), input-line-format could be defined as '.*' and line-regexgroup-for-fix defined as zero 0. (In regex group 0 is a 'special' group which returns the entire match.)
NOTE: Running this regex is the single biggest user of CPU in fixgrep because the regex is run against every line in the file/pipe being processed. So it pays to experiment with different regexes to find one that is fastest. The regex does not need to match the _whole_ line, just the part of the line that indicates it's a line of fix, and a regex group (brackets) which captures the fix message.

-s,--sort-by-tags

Defines the preferred order of the fix tags in the formatted output.
Example usage:
fixgrep -s 35,11
Let's face it, some tags are more interesting than others. This parameter allows you to display the more 'interesting' tags at the front of the outputted message.

-t,--only-include-tags

Tags to include in the formatted fix.
Example usage:
fixgrep -t 35,55,11
A comma separated list of tags numbers to include in the output fix. Any other fields are discarded.

-v,--exclude-messages-of-type

Comma separated list of msgType codes. Can be used to hide messages of certain types from being displayed.
Example usage:
fixgrep -v A,O
e.g. To 'hide' Logon and Heartbeat messages, this parameter could be defined as 'A,0'

-V,--vertical-format

View messages in vertical format. Turned off by default.

-G,--suppress-indent-group-repeats

Suppress indenting of group repeats in vertical format.
Often when viewing messages which have a lot of repeating groups e.g. prices, it is useful to see the repeating groups indented. By default, groups will be indented in vertical formatting. Use this option to suppress this behaviour. Has no effect when viewing messages in the default horizontal format. Note, indentation will also be suppressed if the user is attempting to sort tags.

-x,--debug

Run in debug mode. Stack traces are displayed. Logging is written to fixgrep.log in the fixgrep directory.

-?,--help

Displays help text
Example usage:
fixgrep -?

--256-color-demo

Displays a table of 256 colors using 8 bit Ansi Escape codes.
Most modern consoles support 256 colors. To use any of these colors in your highlights, prefix the msgType with 'Fg' or 'Bg' depending on whether you wish to highlight the foreground or background.'
If your console supports 256 colors, this demo should show a table like the one below:
0123456789101112131415
161718192021222324252627282930313233343536373839404142434445464748495051
525354555657585960616263646566676869707172737475767778798081828384858687
888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
232233234235236237238239240241242243244245246247248249250251252253254255

--16-color-demo

Displays a list of 16 foreground colors and 16 background colors using 16 color Ansi Escape codes.
Most consoles support 16 colors. To use any of these colors in your highlights, prefix the htmlClass of the colors below with 'Fg' or 'Bg' depending on whether you wish to highlight the foreground or background. E.g. FgWhite, BgRed. To find out whether your console supports these colors, run this demo by specifying this option.
If your console supports 16 colors, this demo should show a table like the one below:

Foreground colors

FgBlackFgRedFgGreenFgYellowFgBlueFgPurpleFgCyanFgWhiteFgGrayFgBrightRedFgBrightGreenFgBrightYellowFgBrightBlueFgBrightMagentaFgBrightCyanFgBrightWhite

Background colors

BgBlackBgRedBgGreenBgYellowBgBlueBgPurpleBgCyanBgWhiteBgGrayBgBrightRedBgBrightGreenBgBrightYellowBgBrightBlueBgBrightMagentaBgBrightCyanBgBrightWhite

--man

Displays man page.
Running with this command will print out the man page. You can also use 'fixgrep man' (no dashes) which will run man and pipe it into less -R which preserves ansi colors. Or 'fixgrep man online' which will launch the fixgrep online help into your default browser.

--html

Displays results in HTML format.
Displays as raw html. No css, header or footers will be output.

--html-page

Displays results in a fully formed HTML page.
Outputs html ready to be displayed in a browser. Will include headers and footers. Will also include inline css to format the fix appropriately. You can also used the -l argument if running on a operating system with a browser, to launch the page into your default browser.

--gimme-css

Downloads a copy of the default fixgrep.css file to use with any fixgrep output formatted in HTML.

--fix-spec-path,--fix-spec

Specifies an alternative fixspec definition to use. Spec must be in the format used by quickfix. Default spec is 5.0-SP2.
Example usage:
fixgrep --fix-spec-path fix40_modified.xml
FixGrep first looks for the file relative to the current working directory. If it is not found there, then FixGrep will look on the classpath. Examples: my-fix-spec.xml path/to/my-fix-spec.xml /package/path/to/my-fix-spec.xml

Output formatting

fixgrep supports two basic styles of formatting:
And each of these formats can be viewed in the console, or as html.
There are four different properties that can be used to define how output fix is formatted.
Each of these properties is a specification of how each fix message should be displayed in the corresponding display mode.
These properties are free text, and can include any of the following tokens:
tokendescription
${senderToTargetCompIdDirection}will display the compIds of the current msg. e.g. ABC->DEF
${msgColor}will 'start' formatting text using the pre-defined color for the particular FIX message type.
${msgReset}stops formatting text using the pre-defined color for the FIX message.
${msgTypeName}displays the FIX msg type htmlClass & sub-type, e.g. NewOrderSingle, CancelRequest, Exec.Fill
${msgFix}displays the formatted FIX message
${n}displays the value of that fix tag. e.g. for a NewOrderSingle ${35} would print 'D'
$n(note, no braces), will print the captured regex group 'n' from the regex specified in the parameter input-line-format (or property input.line.format).
Below you can see the default values for these settings. They can be overridden in the application.properties file that ships with fixgrep.

output.format.horizontal.console

${msgFix}

output.format.horizontal.html

${msgFix}

output.format.vertical.console

================================================================================ ${msgColor}${msgTypeName}${colorReset} ================================================================================ ${msgFix}

output.format.vertical.html

<div class='msg-header'> ================================================================================</br> ${msgColor}${msgTypeName}${colorReset}<br/> ================================================================================ </div> ${msgFix} <br/>

Examples

Examples are being applied to the following lines of fix. I have purposefully over simplied these fix messages and stripped them down so that they might fit horizontally on a console:
35=D|11=C28|55=AUD/USD|54=2|38=1464820|44=100.026
35=8|11=C28|150=0|151=1464820|14=0|44=100.02
35=G|11=C32|38=1465320|40=2|44=100.12
35=8|11=C32|150=5|151=1465320|14=0|44=100.12
35=8|11=C32|150=F|151=1072490|14=392830|44=100.00

Horizontal Formatting

By default fixgrep formats fix in 'horizontal format', i.e. one fix message per line
This is how fix messages will appear by default by fixgrep. Notice that the date has been stripped from the front of each message. See later examples on how to add this date back in.
[MsgType]35=D[NEWORDERSINGLE]|[ClOrdID]11=C28|[Symbol]55=AUD/USD|[Side]54=2[SELL]|[OrderQty]38=1464820|[Price]44=100.026
[MsgType]35=8[EXECUTIONREPORT]|[ClOrdID]11=C28|[ExecType]150=0[NEW]|[LeavesQty]151=1464820|[CumQty]14=0|[Price]44=100.02
[MsgType]35=G[ORDERCANCELREPLACEREQUEST]|[ClOrdID]11=C32|[OrderQty]38=1465320|[OrdType]40=2[LIMIT]|[Price]44=100.12
[MsgType]35=8[EXECUTIONREPORT]|[ClOrdID]11=C32|[ExecType]150=5[REPLACED]|[LeavesQty]151=1465320|[CumQty]14=0|[Price]44=100.12
[MsgType]35=8[EXECUTIONREPORT]|[ClOrdID]11=C32|[ExecType]150=F[FILL]|[LeavesQty]151=1072490|[CumQty]14=392830|[Price]44=100.00
Exclude tags 55 and 11.
--exclude-tags 55,11
[MsgType]35=D[NEWORDERSINGLE]|[Side]54=2[SELL]|[OrderQty]38=1464820|[Price]44=100.026
[MsgType]35=8[EXECUTIONREPORT]|[ExecType]150=0[NEW]|[LeavesQty]151=1464820|[CumQty]14=0|[Price]44=100.02
[MsgType]35=G[ORDERCANCELREPLACEREQUEST]|[OrderQty]38=1465320|[OrdType]40=2[LIMIT]|[Price]44=100.12
[MsgType]35=8[EXECUTIONREPORT]|[ExecType]150=5[REPLACED]|[LeavesQty]151=1465320|[CumQty]14=0|[Price]44=100.12
[MsgType]35=8[EXECUTIONREPORT]|[ExecType]150=F[FILL]|[LeavesQty]151=1072490|[CumQty]14=392830|[Price]44=100.00
Same configuration to exclude tags 55,11 but using short form option -e
-e 55,11
[MsgType]35=D[NEWORDERSINGLE]|[Side]54=2[SELL]|[OrderQty]38=1464820|[Price]44=100.026
[MsgType]35=8[EXECUTIONREPORT]|[ExecType]150=0[NEW]|[LeavesQty]151=1464820|[CumQty]14=0|[Price]44=100.02
[MsgType]35=G[ORDERCANCELREPLACEREQUEST]|[OrderQty]38=1465320|[OrdType]40=2[LIMIT]|[Price]44=100.12
[MsgType]35=8[EXECUTIONREPORT]|[ExecType]150=5[REPLACED]|[LeavesQty]151=1465320|[CumQty]14=0|[Price]44=100.12
[MsgType]35=8[EXECUTIONREPORT]|[ExecType]150=F[FILL]|[LeavesQty]151=1072490|[CumQty]14=392830|[Price]44=100.00
Excludes messages of type 8 (ExecutionReport).
--exclude-messages-of-type 8
[MsgType]35=D[NEWORDERSINGLE]|[ClOrdID]11=C28|[Symbol]55=AUD/USD|[Side]54=2[SELL]|[OrderQty]38=1464820|[Price]44=100.026
[MsgType]35=G[ORDERCANCELREPLACEREQUEST]|[ClOrdID]11=C32|[OrderQty]38=1465320|[OrdType]40=2[LIMIT]|[Price]44=100.12
Same exclusion of ExecutionReports using the 'short form' option v
-v 8
[MsgType]35=D[NEWORDERSINGLE]|[ClOrdID]11=C28|[Symbol]55=AUD/USD|[Side]54=2[SELL]|[OrderQty]38=1464820|[Price]44=100.026
[MsgType]35=G[ORDERCANCELREPLACEREQUEST]|[ClOrdID]11=C32|[OrderQty]38=1465320|[OrdType]40=2[LIMIT]|[Price]44=100.12
Excluding messages of type D (NewOrderSingle)
-v D
[MsgType]35=8[EXECUTIONREPORT]|[ClOrdID]11=C28|[ExecType]150=0[NEW]|[LeavesQty]151=1464820|[CumQty]14=0|[Price]44=100.02
[MsgType]35=G[ORDERCANCELREPLACEREQUEST]|[ClOrdID]11=C32|[OrderQty]38=1465320|[OrdType]40=2[LIMIT]|[Price]44=100.12
[MsgType]35=8[EXECUTIONREPORT]|[ClOrdID]11=C32|[ExecType]150=5[REPLACED]|[LeavesQty]151=1465320|[CumQty]14=0|[Price]44=100.12
[MsgType]35=8[EXECUTIONREPORT]|[ClOrdID]11=C32|[ExecType]150=F[FILL]|[LeavesQty]151=1072490|[CumQty]14=392830|[Price]44=100.00
Excluding both messages of type D (NewOrderSingle) and of type 8 (ExecutionReport)
-v D,8
[MsgType]35=G[ORDERCANCELREPLACEREQUEST]|[ClOrdID]11=C32|[OrderQty]38=1465320|[OrdType]40=2[LIMIT]|[Price]44=100.12
Same exclusion, but using repeated options.
-v D -v 8
[MsgType]35=G[ORDERCANCELREPLACEREQUEST]|[ClOrdID]11=C32|[OrderQty]38=1465320|[OrdType]40=2[LIMIT]|[Price]44=100.12
Set annotations to 'outside' meaning the annotated tag will sit before the number, and the annotated value will sit after the valueRaw. Like this [tagAnnotation]number=valueRaw[valueAnnotation], e.g. [Side]54=2[SELL]. This is the default annotation format used by fixgrep, so don't be surprised if the formatted fix did not change.
--tag-annotations outsideAnnotated
[MsgType]35=D[NEWORDERSINGLE]|[ClOrdID]11=C28|[Symbol]55=AUD/USD|[Side]54=2[SELL]|[OrderQty]38=1464820|[Price]44=100.026
[MsgType]35=8[EXECUTIONREPORT]|[ClOrdID]11=C28|[ExecType]150=0[NEW]|[LeavesQty]151=1464820|[CumQty]14=0|[Price]44=100.02
[MsgType]35=G[ORDERCANCELREPLACEREQUEST]|[ClOrdID]11=C32|[OrderQty]38=1465320|[OrdType]40=2[LIMIT]|[Price]44=100.12
[MsgType]35=8[EXECUTIONREPORT]|[ClOrdID]11=C32|[ExecType]150=5[REPLACED]|[LeavesQty]151=1465320|[CumQty]14=0|[Price]44=100.12
[MsgType]35=8[EXECUTIONREPORT]|[ClOrdID]11=C32|[ExecType]150=F[FILL]|[LeavesQty]151=1072490|[CumQty]14=392830|[Price]44=100.00
Same, but using the short form option 'a'
-a outsideAnnotated
[MsgType]35=D[NEWORDERSINGLE]|[ClOrdID]11=C28|[Symbol]55=AUD/USD|[Side]54=2[SELL]|[OrderQty]38=1464820|[Price]44=100.026
[MsgType]35=8[EXECUTIONREPORT]|[ClOrdID]11=C28|[ExecType]150=0[NEW]|[LeavesQty]151=1464820|[CumQty]14=0|[Price]44=100.02
[MsgType]35=G[ORDERCANCELREPLACEREQUEST]|[ClOrdID]11=C32|[OrderQty]38=1465320|[OrdType]40=2[LIMIT]|[Price]44=100.12
[MsgType]35=8[EXECUTIONREPORT]|[ClOrdID]11=C32|[ExecType]150=5[REPLACED]|[LeavesQty]151=1465320|[CumQty]14=0|[Price]44=100.12
[MsgType]35=8[EXECUTIONREPORT]|[ClOrdID]11=C32|[ExecType]150=F[FILL]|[LeavesQty]151=1072490|[CumQty]14=392830|[Price]44=100.00
Same, but using abbreviated form 'ba' meaning 'before-after'
-a ba
[MsgType]35=D[NEWORDERSINGLE]|[ClOrdID]11=C28|[Symbol]55=AUD/USD|[Side]54=2[SELL]|[OrderQty]38=1464820|[Price]44=100.026
[MsgType]35=8[EXECUTIONREPORT]|[ClOrdID]11=C28|[ExecType]150=0[NEW]|[LeavesQty]151=1464820|[CumQty]14=0|[Price]44=100.02
[MsgType]35=G[ORDERCANCELREPLACEREQUEST]|[ClOrdID]11=C32|[OrderQty]38=1465320|[OrdType]40=2[LIMIT]|[Price]44=100.12
[MsgType]35=8[EXECUTIONREPORT]|[ClOrdID]11=C32|[ExecType]150=5[REPLACED]|[LeavesQty]151=1465320|[CumQty]14=0|[Price]44=100.12
[MsgType]35=8[EXECUTIONREPORT]|[ClOrdID]11=C32|[ExecType]150=F[FILL]|[LeavesQty]151=1072490|[CumQty]14=392830|[Price]44=100.00
Inside annotation, meaning the annotated tag will sit after the number, and the annotated value will sit before the valueRaw. Like this number[tagAnnotation]=[valueAnnotation]valueRaw, e.g. 54[Side]=[SELL]2
-a insideAnnotated
35[MsgType]=[NEWORDERSINGLE]D|11[ClOrdID]=C28|55[Symbol]=AUD/USD|54[Side]=[SELL]2|38[OrderQty]=1464820|44[Price]=100.026
35[MsgType]=[EXECUTIONREPORT]8|11[ClOrdID]=C28|150[ExecType]=[NEW]0|151[LeavesQty]=1464820|14[CumQty]=0|44[Price]=100.02
35[MsgType]=[ORDERCANCELREPLACEREQUEST]G|11[ClOrdID]=C32|38[OrderQty]=1465320|40[OrdType]=[LIMIT]2|44[Price]=100.12
35[MsgType]=[EXECUTIONREPORT]8|11[ClOrdID]=C32|150[ExecType]=[REPLACED]5|151[LeavesQty]=1465320|14[CumQty]=0|44[Price]=100.12
35[MsgType]=[EXECUTIONREPORT]8|11[ClOrdID]=C32|150[ExecType]=[FILL]F|151[LeavesQty]=1072490|14[CumQty]=392830|44[Price]=100.00
Same as 'insideAnnotated' but specified in abbreviated form 'ab' meaning after-before.
-a ab
35[MsgType]=[NEWORDERSINGLE]D|11[ClOrdID]=C28|55[Symbol]=AUD/USD|54[Side]=[SELL]2|38[OrderQty]=1464820|44[Price]=100.026
35[MsgType]=[EXECUTIONREPORT]8|11[ClOrdID]=C28|150[ExecType]=[NEW]0|151[LeavesQty]=1464820|14[CumQty]=0|44[Price]=100.02
35[MsgType]=[ORDERCANCELREPLACEREQUEST]G|11[ClOrdID]=C32|38[OrderQty]=1465320|40[OrdType]=[LIMIT]2|44[Price]=100.12
35[MsgType]=[EXECUTIONREPORT]8|11[ClOrdID]=C32|150[ExecType]=[REPLACED]5|151[LeavesQty]=1465320|14[CumQty]=0|44[Price]=100.12
35[MsgType]=[EXECUTIONREPORT]8|11[ClOrdID]=C32|150[ExecType]=[FILL]F|151[LeavesQty]=1072490|14[CumQty]=392830|44[Price]=100.00
Annotations set to before-none, meaning only Tag annotations will be printed, before the raw tag value.
-a b_
[MsgType]35=D|[ClOrdID]11=C28|[Symbol]55=AUD/USD|[Side]54=2|[OrderQty]38=1464820|[Price]44=100.026
[MsgType]35=8|[ClOrdID]11=C28|[ExecType]150=0|[LeavesQty]151=1464820|[CumQty]14=0|[Price]44=100.02
[MsgType]35=G|[ClOrdID]11=C32|[OrderQty]38=1465320|[OrdType]40=2|[Price]44=100.12
[MsgType]35=8|[ClOrdID]11=C32|[ExecType]150=5|[LeavesQty]151=1465320|[CumQty]14=0|[Price]44=100.12
[MsgType]35=8|[ClOrdID]11=C32|[ExecType]150=F|[LeavesQty]151=1072490|[CumQty]14=392830|[Price]44=100.00
Annotations set to after-none, meaning only Tag annotations will be printed, after the raw tag value.
-a a_
35[MsgType]=D|11[ClOrdID]=C28|55[Symbol]=AUD/USD|54[Side]=2|38[OrderQty]=1464820|44[Price]=100.026
35[MsgType]=8|11[ClOrdID]=C28|150[ExecType]=0|151[LeavesQty]=1464820|14[CumQty]=0|44[Price]=100.02
35[MsgType]=G|11[ClOrdID]=C32|38[OrderQty]=1465320|40[OrdType]=2|44[Price]=100.12
35[MsgType]=8|11[ClOrdID]=C32|150[ExecType]=5|151[LeavesQty]=1465320|14[CumQty]=0|44[Price]=100.12
35[MsgType]=8|11[ClOrdID]=C32|150[ExecType]=F|151[LeavesQty]=1072490|14[CumQty]=392830|44[Price]=100.00
Annotations set to none-before, meaning only Tag annotations will be printed, before the raw tag value.
-a _b
35=[NEWORDERSINGLE]D|11=C28|55=AUD/USD|54=[SELL]2|38=1464820|44=100.026
35=[EXECUTIONREPORT]8|11=C28|150=[NEW]0|151=1464820|14=0|44=100.02
35=[ORDERCANCELREPLACEREQUEST]G|11=C32|38=1465320|40=[LIMIT]2|44=100.12
35=[EXECUTIONREPORT]8|11=C32|150=[REPLACED]5|151=1465320|14=0|44=100.12
35=[EXECUTIONREPORT]8|11=C32|150=[FILL]F|151=1072490|14=392830|44=100.00
Annotations set to none-after, meaning only Tag annotations will be printed, after the raw tag value.
-a _a
35=D[NEWORDERSINGLE]|11=C28|55=AUD/USD|54=2[SELL]|38=1464820|44=100.026
35=8[EXECUTIONREPORT]|11=C28|150=0[NEW]|151=1464820|14=0|44=100.02
35=G[ORDERCANCELREPLACEREQUEST]|11=C32|38=1465320|40=2[LIMIT]|44=100.12
35=8[EXECUTIONREPORT]|11=C32|150=5[REPLACED]|151=1465320|14=0|44=100.12
35=8[EXECUTIONREPORT]|11=C32|150=F[FILL]|151=1072490|14=392830|44=100.00
Configuring NO annotations.
-a __
35=D|11=C28|55=AUD/USD|54=2|38=1464820|44=100.026
35=8|11=C28|150=0|151=1464820|14=0|44=100.02
35=G|11=C32|38=1465320|40=2|44=100.12
35=8|11=C32|150=5|151=1465320|14=0|44=100.12
35=8|11=C32|150=F|151=1072490|14=392830|44=100.00
Another way of configuring NO annotations.
-a none
35=D|11=C28|55=AUD/USD|54=2|38=1464820|44=100.026
35=8|11=C28|150=0|151=1464820|14=0|44=100.02
35=G|11=C32|38=1465320|40=2|44=100.12
35=8|11=C32|150=5|151=1465320|14=0|44=100.12
35=8|11=C32|150=F|151=1072490|14=392830|44=100.00
Replace tags and values with annotations (where available)
-a rr
MsgType=NEWORDERSINGLE|ClOrdID=C28|Symbol=AUD/USD|Side=SELL|OrderQty=1464820|Price=100.026
MsgType=EXECUTIONREPORT|ClOrdID=C28|ExecType=NEW|LeavesQty=1464820|CumQty=0|Price=100.02
MsgType=ORDERCANCELREPLACEREQUEST|ClOrdID=C32|OrderQty=1465320|OrdType=LIMIT|Price=100.12
MsgType=EXECUTIONREPORT|ClOrdID=C32|ExecType=REPLACED|LeavesQty=1465320|CumQty=0|Price=100.12
MsgType=EXECUTIONREPORT|ClOrdID=C32|ExecType=FILL|LeavesQty=1072490|CumQty=392830|Price=100.00
Same effect (replace with annotations) but using abbreviated single character option.
-a r
MsgType=NEWORDERSINGLE|ClOrdID=C28|Symbol=AUD/USD|Side=SELL|OrderQty=1464820|Price=100.026
MsgType=EXECUTIONREPORT|ClOrdID=C28|ExecType=NEW|LeavesQty=1464820|CumQty=0|Price=100.02
MsgType=ORDERCANCELREPLACEREQUEST|ClOrdID=C32|OrderQty=1465320|OrdType=LIMIT|Price=100.12
MsgType=EXECUTIONREPORT|ClOrdID=C32|ExecType=REPLACED|LeavesQty=1465320|CumQty=0|Price=100.12
MsgType=EXECUTIONREPORT|ClOrdID=C32|ExecType=FILL|LeavesQty=1072490|CumQty=392830|Price=100.00
Will only print messages of type D (NewOrderSingle).
--include-only-messages-of-type D
[MsgType]35=D[NEWORDERSINGLE]|[ClOrdID]11=C28|[Symbol]55=AUD/USD|[Side]54=2[SELL]|[OrderQty]38=1464820|[Price]44=100.026
Same inclusion of just NewOrderSingle messages, but option specified in short form 'm'
-m D
[MsgType]35=D[NEWORDERSINGLE]|[ClOrdID]11=C28|[Symbol]55=AUD/USD|[Side]54=2[SELL]|[OrderQty]38=1464820|[Price]44=100.026
Only show NewOrderSingles and ExecutionReports
-m D,8
[MsgType]35=D[NEWORDERSINGLE]|[ClOrdID]11=C28|[Symbol]55=AUD/USD|[Side]54=2[SELL]|[OrderQty]38=1464820|[Price]44=100.026
[MsgType]35=8[EXECUTIONREPORT]|[ClOrdID]11=C28|[ExecType]150=0[NEW]|[LeavesQty]151=1464820|[CumQty]14=0|[Price]44=100.02
[MsgType]35=8[EXECUTIONREPORT]|[ClOrdID]11=C32|[ExecType]150=5[REPLACED]|[LeavesQty]151=1465320|[CumQty]14=0|[Price]44=100.12
[MsgType]35=8[EXECUTIONREPORT]|[ClOrdID]11=C32|[ExecType]150=F[FILL]|[LeavesQty]151=1072490|[CumQty]14=392830|[Price]44=100.00
Set output delimiter to ':'. (Default is pipe '|')
--output-delimiter :
[MsgType]35=D[NEWORDERSINGLE]:[ClOrdID]11=C28:[Symbol]55=AUD/USD:[Side]54=2[SELL]:[OrderQty]38=1464820:[Price]44=100.026
[MsgType]35=8[EXECUTIONREPORT]:[ClOrdID]11=C28:[ExecType]150=0[NEW]:[LeavesQty]151=1464820:[CumQty]14=0:[Price]44=100.02
[MsgType]35=G[ORDERCANCELREPLACEREQUEST]:[ClOrdID]11=C32:[OrderQty]38=1465320:[OrdType]40=2[LIMIT]:[Price]44=100.12
[MsgType]35=8[EXECUTIONREPORT]:[ClOrdID]11=C32:[ExecType]150=5[REPLACED]:[LeavesQty]151=1465320:[CumQty]14=0:[Price]44=100.12
[MsgType]35=8[EXECUTIONREPORT]:[ClOrdID]11=C32:[ExecType]150=F[FILL]:[LeavesQty]151=1072490:[CumQty]14=392830:[Price]44=100.00
Same, but using short form option -D
-D :
[MsgType]35=D[NEWORDERSINGLE]:[ClOrdID]11=C28:[Symbol]55=AUD/USD:[Side]54=2[SELL]:[OrderQty]38=1464820:[Price]44=100.026
[MsgType]35=8[EXECUTIONREPORT]:[ClOrdID]11=C28:[ExecType]150=0[NEW]:[LeavesQty]151=1464820:[CumQty]14=0:[Price]44=100.02
[MsgType]35=G[ORDERCANCELREPLACEREQUEST]:[ClOrdID]11=C32:[OrderQty]38=1465320:[OrdType]40=2[LIMIT]:[Price]44=100.12
[MsgType]35=8[EXECUTIONREPORT]:[ClOrdID]11=C32:[ExecType]150=5[REPLACED]:[LeavesQty]151=1465320:[CumQty]14=0:[Price]44=100.12
[MsgType]35=8[EXECUTIONREPORT]:[ClOrdID]11=C32:[ExecType]150=F[FILL]:[LeavesQty]151=1072490:[CumQty]14=392830:[Price]44=100.00
For each fix line, show tags 55 then 11 first if they exist, followed by other tags in the order that they originally appeared.
--sort-by-tags 55,11
[Symbol]55=AUD/USD|[ClOrdID]11=C28|[MsgType]35=D[NEWORDERSINGLE]|[Side]54=2[SELL]|[OrderQty]38=1464820|[Price]44=100.026
[ClOrdID]11=C28|[MsgType]35=8[EXECUTIONREPORT]|[ExecType]150=0[NEW]|[LeavesQty]151=1464820|[CumQty]14=0|[Price]44=100.02
[ClOrdID]11=C32|[MsgType]35=G[ORDERCANCELREPLACEREQUEST]|[OrderQty]38=1465320|[OrdType]40=2[LIMIT]|[Price]44=100.12
[ClOrdID]11=C32|[MsgType]35=8[EXECUTIONREPORT]|[ExecType]150=5[REPLACED]|[LeavesQty]151=1465320|[CumQty]14=0|[Price]44=100.12
[ClOrdID]11=C32|[MsgType]35=8[EXECUTIONREPORT]|[ExecType]150=F[FILL]|[LeavesQty]151=1072490|[CumQty]14=392830|[Price]44=100.00
Same configuration, but using short form option -s.
-s 55,11
[Symbol]55=AUD/USD|[ClOrdID]11=C28|[MsgType]35=D[NEWORDERSINGLE]|[Side]54=2[SELL]|[OrderQty]38=1464820|[Price]44=100.026
[ClOrdID]11=C28|[MsgType]35=8[EXECUTIONREPORT]|[ExecType]150=0[NEW]|[LeavesQty]151=1464820|[CumQty]14=0|[Price]44=100.02
[ClOrdID]11=C32|[MsgType]35=G[ORDERCANCELREPLACEREQUEST]|[OrderQty]38=1465320|[OrdType]40=2[LIMIT]|[Price]44=100.12
[ClOrdID]11=C32|[MsgType]35=8[EXECUTIONREPORT]|[ExecType]150=5[REPLACED]|[LeavesQty]151=1465320|[CumQty]14=0|[Price]44=100.12
[ClOrdID]11=C32|[MsgType]35=8[EXECUTIONREPORT]|[ExecType]150=F[FILL]|[LeavesQty]151=1072490|[CumQty]14=392830|[Price]44=100.00
Show tags 55, then 11, then 35 first on each line, followed by other tags in the order that they originally appeared.
-s 55,11,35
[Symbol]55=AUD/USD|[ClOrdID]11=C28|[MsgType]35=D[NEWORDERSINGLE]|[Side]54=2[SELL]|[OrderQty]38=1464820|[Price]44=100.026
[ClOrdID]11=C28|[MsgType]35=8[EXECUTIONREPORT]|[ExecType]150=0[NEW]|[LeavesQty]151=1464820|[CumQty]14=0|[Price]44=100.02
[ClOrdID]11=C32|[MsgType]35=G[ORDERCANCELREPLACEREQUEST]|[OrderQty]38=1465320|[OrdType]40=2[LIMIT]|[Price]44=100.12
[ClOrdID]11=C32|[MsgType]35=8[EXECUTIONREPORT]|[ExecType]150=5[REPLACED]|[LeavesQty]151=1465320|[CumQty]14=0|[Price]44=100.12
[ClOrdID]11=C32|[MsgType]35=8[EXECUTIONREPORT]|[ExecType]150=F[FILL]|[LeavesQty]151=1072490|[CumQty]14=392830|[Price]44=100.00
Only show tag 35.
--only-include-tags 35
[MsgType]35=D[NEWORDERSINGLE]
[MsgType]35=8[EXECUTIONREPORT]
[MsgType]35=G[ORDERCANCELREPLACEREQUEST]
[MsgType]35=8[EXECUTIONREPORT]
[MsgType]35=8[EXECUTIONREPORT]
Same configuration to only show tag 35, but using short form option -t
-t 35
[MsgType]35=D[NEWORDERSINGLE]
[MsgType]35=8[EXECUTIONREPORT]
[MsgType]35=G[ORDERCANCELREPLACEREQUEST]
[MsgType]35=8[EXECUTIONREPORT]
[MsgType]35=8[EXECUTIONREPORT]
Only show tags 35 and 55
-t 35,55
[MsgType]35=D[NEWORDERSINGLE]|[Symbol]55=AUD/USD
[MsgType]35=8[EXECUTIONREPORT]
[MsgType]35=G[ORDERCANCELREPLACEREQUEST]
[MsgType]35=8[EXECUTIONREPORT]
[MsgType]35=8[EXECUTIONREPORT]
Only show tags 35 and 11
-t 35,11
[MsgType]35=D[NEWORDERSINGLE]|[ClOrdID]11=C28
[MsgType]35=8[EXECUTIONREPORT]|[ClOrdID]11=C28
[MsgType]35=G[ORDERCANCELREPLACEREQUEST]|[ClOrdID]11=C32
[MsgType]35=8[EXECUTIONREPORT]|[ClOrdID]11=C32
[MsgType]35=8[EXECUTIONREPORT]|[ClOrdID]11=C32
Highlight tag 35 irrespective of value.
--highlights 35
[MsgType]35=D[NEWORDERSINGLE]|[ClOrdID]11=C28|[Symbol]55=AUD/USD|[Side]54=2[SELL]|[OrderQty]38=1464820|[Price]44=100.026
[MsgType]35=8[EXECUTIONREPORT]|[ClOrdID]11=C28|[ExecType]150=0[NEW]|[LeavesQty]151=1464820|[CumQty]14=0|[Price]44=100.02
[MsgType]35=G[ORDERCANCELREPLACEREQUEST]|[ClOrdID]11=C32|[OrderQty]38=1465320|[OrdType]40=2[LIMIT]|[Price]44=100.12
[MsgType]35=8[EXECUTIONREPORT]|[ClOrdID]11=C32|[ExecType]150=5[REPLACED]|[LeavesQty]151=1465320|[CumQty]14=0|[Price]44=100.12
[MsgType]35=8[EXECUTIONREPORT]|[ClOrdID]11=C32|[ExecType]150=F[FILL]|[LeavesQty]151=1072490|[CumQty]14=392830|[Price]44=100.00
Same highlight but using short form option -h
-h 35
[MsgType]35=D[NEWORDERSINGLE]|[ClOrdID]11=C28|[Symbol]55=AUD/USD|[Side]54=2[SELL]|[OrderQty]38=1464820|[Price]44=100.026
[MsgType]35=8[EXECUTIONREPORT]|[ClOrdID]11=C28|[ExecType]150=0[NEW]|[LeavesQty]151=1464820|[CumQty]14=0|[Price]44=100.02
[MsgType]35=G[ORDERCANCELREPLACEREQUEST]|[ClOrdID]11=C32|[OrderQty]38=1465320|[OrdType]40=2[LIMIT]|[Price]44=100.12
[MsgType]35=8[EXECUTIONREPORT]|[ClOrdID]11=C32|[ExecType]150=5[REPLACED]|[LeavesQty]151=1465320|[CumQty]14=0|[Price]44=100.12
[MsgType]35=8[EXECUTIONREPORT]|[ClOrdID]11=C32|[ExecType]150=F[FILL]|[LeavesQty]151=1072490|[CumQty]14=392830|[Price]44=100.00
Highlight tag 35 when it's value is 8 (ExecutionReport)
-h 35=8
[MsgType]35=D[NEWORDERSINGLE]|[ClOrdID]11=C28|[Symbol]55=AUD/USD|[Side]54=2[SELL]|[OrderQty]38=1464820|[Price]44=100.026
[MsgType]35=8[EXECUTIONREPORT]|[ClOrdID]11=C28|[ExecType]150=0[NEW]|[LeavesQty]151=1464820|[CumQty]14=0|[Price]44=100.02
[MsgType]35=G[ORDERCANCELREPLACEREQUEST]|[ClOrdID]11=C32|[OrderQty]38=1465320|[OrdType]40=2[LIMIT]|[Price]44=100.12
[MsgType]35=8[EXECUTIONREPORT]|[ClOrdID]11=C32|[ExecType]150=5[REPLACED]|[LeavesQty]151=1465320|[CumQty]14=0|[Price]44=100.12
[MsgType]35=8[EXECUTIONREPORT]|[ClOrdID]11=C32|[ExecType]150=F[FILL]|[LeavesQty]151=1072490|[CumQty]14=392830|[Price]44=100.00
Highlight whole lines when tag 35=8 (ExecutionReport)
-h 35=8:Msg
[MsgType]35=D[NEWORDERSINGLE]|[ClOrdID]11=C28|[Symbol]55=AUD/USD|[Side]54=2[SELL]|[OrderQty]38=1464820|[Price]44=100.026
[MsgType]35=8[EXECUTIONREPORT]|[ClOrdID]11=C28|[ExecType]150=0[NEW]|[LeavesQty]151=1464820|[CumQty]14=0|[Price]44=100.02
[MsgType]35=G[ORDERCANCELREPLACEREQUEST]|[ClOrdID]11=C32|[OrderQty]38=1465320|[OrdType]40=2[LIMIT]|[Price]44=100.12
[MsgType]35=8[EXECUTIONREPORT]|[ClOrdID]11=C32|[ExecType]150=5[REPLACED]|[LeavesQty]151=1465320|[CumQty]14=0|[Price]44=100.12
[MsgType]35=8[EXECUTIONREPORT]|[ClOrdID]11=C32|[ExecType]150=F[FILL]|[LeavesQty]151=1072490|[CumQty]14=392830|[Price]44=100.00
Highlight whole lines with background color 3 of the 256 color map, when tag 35=8 (ExecutionReport)
-h 35=8:Bg12:Msg
[MsgType]35=D[NEWORDERSINGLE]|[ClOrdID]11=C28|[Symbol]55=AUD/USD|[Side]54=2[SELL]|[OrderQty]38=1464820|[Price]44=100.026
[MsgType]35=8[EXECUTIONREPORT]|[ClOrdID]11=C28|[ExecType]150=0[NEW]|[LeavesQty]151=1464820|[CumQty]14=0|[Price]44=100.02
[MsgType]35=G[ORDERCANCELREPLACEREQUEST]|[ClOrdID]11=C32|[OrderQty]38=1465320|[OrdType]40=2[LIMIT]|[Price]44=100.12
[MsgType]35=8[EXECUTIONREPORT]|[ClOrdID]11=C32|[ExecType]150=5[REPLACED]|[LeavesQty]151=1465320|[CumQty]14=0|[Price]44=100.12
[MsgType]35=8[EXECUTIONREPORT]|[ClOrdID]11=C32|[ExecType]150=F[FILL]|[LeavesQty]151=1072490|[CumQty]14=392830|[Price]44=100.00
Highlight tags 35 and 55.
-h 35,55
[MsgType]35=D[NEWORDERSINGLE]|[ClOrdID]11=C28|[Symbol]55=AUD/USD|[Side]54=2[SELL]|[OrderQty]38=1464820|[Price]44=100.026
[MsgType]35=8[EXECUTIONREPORT]|[ClOrdID]11=C28|[ExecType]150=0[NEW]|[LeavesQty]151=1464820|[CumQty]14=0|[Price]44=100.02
[MsgType]35=G[ORDERCANCELREPLACEREQUEST]|[ClOrdID]11=C32|[OrderQty]38=1465320|[OrdType]40=2[LIMIT]|[Price]44=100.12
[MsgType]35=8[EXECUTIONREPORT]|[ClOrdID]11=C32|[ExecType]150=5[REPLACED]|[LeavesQty]151=1465320|[CumQty]14=0|[Price]44=100.12
[MsgType]35=8[EXECUTIONREPORT]|[ClOrdID]11=C32|[ExecType]150=F[FILL]|[LeavesQty]151=1072490|[CumQty]14=392830|[Price]44=100.00
Highlight tag 35 with a background color of 8. Highlight tag 55 with a background color of 9.
-h 35:Bg176,55:Bg9
[MsgType]35=D[NEWORDERSINGLE]|[ClOrdID]11=C28|[Symbol]55=AUD/USD|[Side]54=2[SELL]|[OrderQty]38=1464820|[Price]44=100.026
[MsgType]35=8[EXECUTIONREPORT]|[ClOrdID]11=C28|[ExecType]150=0[NEW]|[LeavesQty]151=1464820|[CumQty]14=0|[Price]44=100.02
[MsgType]35=G[ORDERCANCELREPLACEREQUEST]|[ClOrdID]11=C32|[OrderQty]38=1465320|[OrdType]40=2[LIMIT]|[Price]44=100.12
[MsgType]35=8[EXECUTIONREPORT]|[ClOrdID]11=C32|[ExecType]150=5[REPLACED]|[LeavesQty]151=1465320|[CumQty]14=0|[Price]44=100.12
[MsgType]35=8[EXECUTIONREPORT]|[ClOrdID]11=C32|[ExecType]150=F[FILL]|[LeavesQty]151=1072490|[CumQty]14=392830|[Price]44=100.00
When a message has tag 35=D, highlight the whole line. Also highlight tag 55.
-h 35=D:Msg,55
[MsgType]35=D[NEWORDERSINGLE]|[ClOrdID]11=C28|[Symbol]55=AUD/USD|[Side]54=2[SELL]|[OrderQty]38=1464820|[Price]44=100.026
[MsgType]35=8[EXECUTIONREPORT]|[ClOrdID]11=C28|[ExecType]150=0[NEW]|[LeavesQty]151=1464820|[CumQty]14=0|[Price]44=100.02
[MsgType]35=G[ORDERCANCELREPLACEREQUEST]|[ClOrdID]11=C32|[OrderQty]38=1465320|[OrdType]40=2[LIMIT]|[Price]44=100.12
[MsgType]35=8[EXECUTIONREPORT]|[ClOrdID]11=C32|[ExecType]150=5[REPLACED]|[LeavesQty]151=1465320|[CumQty]14=0|[Price]44=100.12
[MsgType]35=8[EXECUTIONREPORT]|[ClOrdID]11=C32|[ExecType]150=F[FILL]|[LeavesQty]151=1072490|[CumQty]14=392830|[Price]44=100.00
Suppress bold text effects in the output fix.
--suppress-bold-tags-and-values
[MsgType]35=D[NEWORDERSINGLE]|[ClOrdID]11=C28|[Symbol]55=AUD/USD|[Side]54=2[SELL]|[OrderQty]38=1464820|[Price]44=100.026
[MsgType]35=8[EXECUTIONREPORT]|[ClOrdID]11=C28|[ExecType]150=0[NEW]|[LeavesQty]151=1464820|[CumQty]14=0|[Price]44=100.02
[MsgType]35=G[ORDERCANCELREPLACEREQUEST]|[ClOrdID]11=C32|[OrderQty]38=1465320|[OrdType]40=2[LIMIT]|[Price]44=100.12
[MsgType]35=8[EXECUTIONREPORT]|[ClOrdID]11=C32|[ExecType]150=5[REPLACED]|[LeavesQty]151=1465320|[CumQty]14=0|[Price]44=100.12
[MsgType]35=8[EXECUTIONREPORT]|[ClOrdID]11=C32|[ExecType]150=F[FILL]|[LeavesQty]151=1072490|[CumQty]14=392830|[Price]44=100.00

Parsing log lines

So far we have looked at examples of options which just change the way the fix message is presented. It is also worth considering how fixgrep parses log files, and how parts of that log line (not just the fix) can be printed in the fixgrep output.
It is common for fix messages to be printed in the same file as application logs. It is also common to have other things printed on the same line as the fix message. Such as timestamps, thread numbers, etc.
Let's consider these log lines as input:
2018-05-30T07:12:34.456 Thread-11 gbfix001 35=D|11=C28|55=AUD/USD|54=2|38=1464820|44=100.026
2018-05-30T07:12:35.101 Thread-11 gbfix001 Processing new order single, ClOrderId=11, mid price captured at time 07:12:34.011=100.3
2018-05-30T07:12:35.101 Thread-11 gbfix001 Sending back PendingNew for OrderId=O26 ClOrderId=11
2018-05-30T07:12:35.101 Thread-11 gbfix001 35=8|11=C28|150=0|151=1464820|14=0|44=100.02
2018-05-30T07:22:12.350 Thread-06 gbfix001 35=G|11=C32|38=1465320|40=2|44=100.12
2018-05-30T07:12:35.101 Thread-06 gbfix002 Amend request recieved for OrderId=O26
2018-05-30T07:22:13.670 Thread-01 gbfix002 35=8|11=C32|150=5|151=1465320|14=0|44=100.12
2018-05-30T07:34:34.060 Thread-13 gbfix002 35=8|11=C32|150=F|151=1072490|14=392830|44=100.00
There is an options (-F --output-format-horizontal-console), which can be used to configure the regular expression that is run against every log line. By default this is:
^(\d{4}-[01]\d-[0-3]\d[T\s][0-2]\d:[0-5]\d:[0-5]\d[\.,]\d+)?.*?(\d+=.*$)
...which translates to 'look for an optional date at the start of the line, followed by any characters, followed by one or more digits, followed by an equals sign.
Parsing our new input lines outputs this:
Parsing new log lines with no arguments.
[MsgType]35=D[NEWORDERSINGLE]|[ClOrdID]11=C28|[Symbol]55=AUD/USD|[Side]54=2[SELL]|[OrderQty]38=1464820|[Price]44=100.026
[ClOrdID]11=100.3
[MsgType]35=8[EXECUTIONREPORT]|[ClOrdID]11=C28|[ExecType]150=0[NEW]|[LeavesQty]151=1464820|[CumQty]14=0|[Price]44=100.02
[MsgType]35=G[ORDERCANCELREPLACEREQUEST]|[ClOrdID]11=C32|[OrderQty]38=1465320|[OrdType]40=2[LIMIT]|[Price]44=100.12
[MsgType]35=8[EXECUTIONREPORT]|[ClOrdID]11=C32|[ExecType]150=5[REPLACED]|[LeavesQty]151=1465320|[CumQty]14=0|[Price]44=100.12
[MsgType]35=8[EXECUTIONREPORT]|[ClOrdID]11=C32|[ExecType]150=F[FILL]|[LeavesQty]151=1072490|[CumQty]14=392830|[Price]44=100.00
In the example above, fixgrep assumed the line containing '...mid price captured at time 07:12:34.011=100.3' contained a fix message because of the '11=100.3' text, it then printed out: '[ClOrdID]11=100.3'. To remedy this, we can use a more specific regex:
--input-line-format ^(\d{4}-[01]\d-[0-3]\d[T\s][0-2]\d:[0-5]\d:[0-5]\d[\.,]\d+)?.*?(35=.*$)
[MsgType]35=D[NEWORDERSINGLE]|[ClOrdID]11=C28|[Symbol]55=AUD/USD|[Side]54=2[SELL]|[OrderQty]38=1464820|[Price]44=100.026
[MsgType]35=8[EXECUTIONREPORT]|[ClOrdID]11=C28|[ExecType]150=0[NEW]|[LeavesQty]151=1464820|[CumQty]14=0|[Price]44=100.02
[MsgType]35=G[ORDERCANCELREPLACEREQUEST]|[ClOrdID]11=C32|[OrderQty]38=1465320|[OrdType]40=2[LIMIT]|[Price]44=100.12
[MsgType]35=8[EXECUTIONREPORT]|[ClOrdID]11=C32|[ExecType]150=5[REPLACED]|[LeavesQty]151=1465320|[CumQty]14=0|[Price]44=100.12
[MsgType]35=8[EXECUTIONREPORT]|[ClOrdID]11=C32|[ExecType]150=F[FILL]|[LeavesQty]151=1072490|[CumQty]14=392830|[Price]44=100.00
That's better. Now that log line is not picked up. Let's assume we do wish to show the date at the start of each line. We do this by specifying $1 at the start of the output-format-horizontal-console.
--output-format-horizontal-console $1:${msgFix} --input-line-format ^(\d{4}-[01]\d-[0-3]\d[T\s][0-2]\d:[0-5]\d:[0-5]\d[\.,]\d+)?.*?(35=.*$)
[MsgType]35=D[NEWORDERSINGLE]|[ClOrdID]11=C28|[Symbol]55=AUD/USD|[Side]54=2[SELL]|[OrderQty]38=1464820|[Price]44=100.026
[MsgType]35=8[EXECUTIONREPORT]|[ClOrdID]11=C28|[ExecType]150=0[NEW]|[LeavesQty]151=1464820|[CumQty]14=0|[Price]44=100.02
[MsgType]35=G[ORDERCANCELREPLACEREQUEST]|[ClOrdID]11=C32|[OrderQty]38=1465320|[OrdType]40=2[LIMIT]|[Price]44=100.12
[MsgType]35=8[EXECUTIONREPORT]|[ClOrdID]11=C32|[ExecType]150=5[REPLACED]|[LeavesQty]151=1465320|[CumQty]14=0|[Price]44=100.12
[MsgType]35=8[EXECUTIONREPORT]|[ClOrdID]11=C32|[ExecType]150=F[FILL]|[LeavesQty]151=1072490|[CumQty]14=392830|[Price]44=100.00
Whilst we're at it, let's just print out the time by slightly modifying the position of the first set of capturing brackets, as the whole date becomes a bit redundant.
--output-format-horizontal-console $1:${msgFix} --input-line-format ^\d{4}-[01]\d-[0-3]\d[T\s]([0-2]\d:[0-5]\d:[0-5]\d[\.,]\d+)?.*?(35=.*$)
[MsgType]35=D[NEWORDERSINGLE]|[ClOrdID]11=C28|[Symbol]55=AUD/USD|[Side]54=2[SELL]|[OrderQty]38=1464820|[Price]44=100.026
[MsgType]35=8[EXECUTIONREPORT]|[ClOrdID]11=C28|[ExecType]150=0[NEW]|[LeavesQty]151=1464820|[CumQty]14=0|[Price]44=100.02
[MsgType]35=G[ORDERCANCELREPLACEREQUEST]|[ClOrdID]11=C32|[OrderQty]38=1465320|[OrdType]40=2[LIMIT]|[Price]44=100.12
[MsgType]35=8[EXECUTIONREPORT]|[ClOrdID]11=C32|[ExecType]150=5[REPLACED]|[LeavesQty]151=1465320|[CumQty]14=0|[Price]44=100.12
[MsgType]35=8[EXECUTIONREPORT]|[ClOrdID]11=C32|[ExecType]150=F[FILL]|[LeavesQty]151=1072490|[CumQty]14=392830|[Price]44=100.00
We can use another pre-defined tag ${msgTypeName} to print out not just the messageType, but also the execType if it's an execution report.
--output-format-horizontal-console $1:${msgTypeName}:${msgFix} --input-line-format ^\d{4}-[01]\d-[0-3]\d[T\s]([0-2]\d:[0-5]\d:[0-5]\d[\.,]\d+)?.*?(35=.*$)
[MsgType]35=D[NEWORDERSINGLE]|[ClOrdID]11=C28|[Symbol]55=AUD/USD|[Side]54=2[SELL]|[OrderQty]38=1464820|[Price]44=100.026
[MsgType]35=8[EXECUTIONREPORT]|[ClOrdID]11=C28|[ExecType]150=0[NEW]|[LeavesQty]151=1464820|[CumQty]14=0|[Price]44=100.02
[MsgType]35=G[ORDERCANCELREPLACEREQUEST]|[ClOrdID]11=C32|[OrderQty]38=1465320|[OrdType]40=2[LIMIT]|[Price]44=100.12
[MsgType]35=8[EXECUTIONREPORT]|[ClOrdID]11=C32|[ExecType]150=5[REPLACED]|[LeavesQty]151=1465320|[CumQty]14=0|[Price]44=100.12
[MsgType]35=8[EXECUTIONREPORT]|[ClOrdID]11=C32|[ExecType]150=F[FILL]|[LeavesQty]151=1072490|[CumQty]14=392830|[Price]44=100.00
And add coloring per message type
--output-format-horizontal-console $1:${msgColor}${msgTypeName}${colorReset}:${msgFix} --input-line-format ^\d{4}-[01]\d-[0-3]\d[T\s]([0-2]\d:[0-5]\d:[0-5]\d[\.,]\d+)?.*?(35=.*$)
[MsgType]35=D[NEWORDERSINGLE]|[ClOrdID]11=C28|[Symbol]55=AUD/USD|[Side]54=2[SELL]|[OrderQty]38=1464820|[Price]44=100.026
[MsgType]35=8[EXECUTIONREPORT]|[ClOrdID]11=C28|[ExecType]150=0[NEW]|[LeavesQty]151=1464820|[CumQty]14=0|[Price]44=100.02
[MsgType]35=G[ORDERCANCELREPLACEREQUEST]|[ClOrdID]11=C32|[OrderQty]38=1465320|[OrdType]40=2[LIMIT]|[Price]44=100.12
[MsgType]35=8[EXECUTIONREPORT]|[ClOrdID]11=C32|[ExecType]150=5[REPLACED]|[LeavesQty]151=1465320|[CumQty]14=0|[Price]44=100.12
[MsgType]35=8[EXECUTIONREPORT]|[ClOrdID]11=C32|[ExecType]150=F[FILL]|[LeavesQty]151=1072490|[CumQty]14=392830|[Price]44=100.00
I'm going to exclude (hide) field 35 as I already have the MessageType printed at the start of the line.
--exclude-tags 35 --output-format-horizontal-console $1:${msgColor}${msgTypeName}${colorReset}:${msgFix} --input-line-format ^\d{4}-[01]\d-[0-3]\d[T\s]([0-2]\d:[0-5]\d:[0-5]\d[\.,]\d+)?.*?(35=.*$)
[ClOrdID]11=C28|[Symbol]55=AUD/USD|[Side]54=2[SELL]|[OrderQty]38=1464820|[Price]44=100.026
[ClOrdID]11=C28|[ExecType]150=0[NEW]|[LeavesQty]151=1464820|[CumQty]14=0|[Price]44=100.02
[ClOrdID]11=C32|[OrderQty]38=1465320|[OrdType]40=2[LIMIT]|[Price]44=100.12
[ClOrdID]11=C32|[ExecType]150=5[REPLACED]|[LeavesQty]151=1465320|[CumQty]14=0|[Price]44=100.12
[ClOrdID]11=C32|[ExecType]150=F[FILL]|[LeavesQty]151=1072490|[CumQty]14=392830|[Price]44=100.00
This is now looking more presentable. If I want to have these settings applied each time I run fixgrep, I just need to modify my ~/.fixgrep/application.properties file. Fixgrep can automatically create this file by running:
fixgrep --install
And populate this file with the corresponding property settings (notice I've replaced the option dashes, with property dots):
exclude.tags=35 output.format.horizontal.console=$1:${msgColor}${msgTypeName}${colorReset}:${msgFix} input.line.format=^\d{4}-[01]\d-[0-3]\d[T\s]([0-2]\d:[0-5]\d:[0-5]\d[\.,]\d+)?.*?(35=.*$)

Vertical Formatting

So far we've looked at examples using horizontal formatting. Sometimes vertical formatting is preferable. Especially when looking at messages containing repeating groups such as prices.
Let's consider this single log lines as input. It contains 3 repeating prices:
35=X|262=ABCD|268=3|279=0|269=0|55=AUD/USD|270=1.12345|279=0|269=1|55=AUD/USD|270=1.12355|279=0|269=1|55=AUD/USD|270=1.12355|1022=FeedA|
The default vertical format is 'non-aligned', which has the benefit that repeating groups can be indented.
-V
================================================================================
MarketDataIncrementalRefresh
================================================================================
[MsgType]35=X[MARKETDATAINCREMENTALREFRESH]
[MDReqID]262=ABCD
[NoMDEntries]268=3
1.
[MDUpdateAction]279=0[NEW]
[MDEntryType]269=0[BID]
[Symbol]55=AUD/USD
[MDEntryPx]270=1.12345
2.
[MDUpdateAction]279=0[NEW]
[MDEntryType]269=1[OFFER]
[Symbol]55=AUD/USD
[MDEntryPx]270=1.12355
3.
[MDUpdateAction]279=0[NEW]
[MDEntryType]269=1[OFFER]
[Symbol]55=AUD/USD
[MDEntryPx]270=1.12355
[MDFeedType]1022=FeedA

To turn off repeating group indenting, set the -G parameter to 'false'.
-V -G false
================================================================================
MarketDataIncrementalRefresh
================================================================================
[MsgType]35=X[MARKETDATAINCREMENTALREFRESH]
[MDReqID]262=ABCD
[NoMDEntries]268=3
[MDUpdateAction]279=0[NEW]
[MDEntryType]269=0[BID]
[Symbol]55=AUD/USD
[MDEntryPx]270=1.12345
[MDUpdateAction]279=0[NEW]
[MDEntryType]269=1[OFFER]
[Symbol]55=AUD/USD
[MDEntryPx]270=1.12355
[MDUpdateAction]279=0[NEW]
[MDEntryType]269=1[OFFER]
[Symbol]55=AUD/USD
[MDEntryPx]270=1.12355
[MDFeedType]1022=FeedA

And to use 'aligned' vertical formatting, use the -A flag. Note that when using 'aligned' vertical formatting, you will not be able to use indented repeating groups.
-V -A
================================================================================
MarketDataIncrementalRefresh
================================================================================
MsgType35=XMARKETDATAINCREMENTALREFRESH
MDReqID262=ABCD
NoMDEntries268=3
MDUpdateAction279=0NEW
MDEntryType269=0BID
Symbol55=AUD/USD
MDEntryPx270=1.12345
MDUpdateAction279=0NEW
MDEntryType269=1OFFER
Symbol55=AUD/USD
MDEntryPx270=1.12355
MDUpdateAction279=0NEW
MDEntryType269=1OFFER
Symbol55=AUD/USD
MDEntryPx270=1.12355
MDFeedType1022=FeedA

Order Grouping

Order grouping allows the grouping of order messages by order. When using Order Grouping:
These messages are grouped by order.
-O
=================================================================================
ORDER orderId:123 clOrdId:ABC
================================================================================
[MsgType]35=D[NEWORDERSINGLE]|[SenderCompID]49=CLIENT|[TargetCompID]56=SERVER|[ClOrdID]11=ABC
[MsgType]35=8[EXECUTIONREPORT]|[SenderCompID]49=SERVER|[TargetCompID]56=CLIENT|[ExecType]150=0[NEW]|[ClOrdID]11=ABC|[OrderID]37=123
[MsgType]35=8[EXECUTIONREPORT]|[SenderCompID]49=SERVER|[TargetCompID]56=CLIENT|[ExecType]150=F[FILL]|[ClOrdID]11=ABC|[OrderID]37=123
[MsgType]35=8[EXECUTIONREPORT]|[SenderCompID]49=SERVER|[TargetCompID]56=CLIENT|[ExecType]150=F[FILL]|[OrderID]37=123
[MsgType]35=G[ORDERCANCELREPLACEREQUEST]|[SenderCompID]49=CLIENT|[TargetCompID]56=SERVER|[OrigClOrdID]41=ABC|[ClOrdID]11=DEF|[OrderID]37=123
[MsgType]35=G[ORDERCANCELREPLACEREQUEST]|[SenderCompID]49=CLIENT|[TargetCompID]56=SERVER|[OrigClOrdID]41=DEF|[ClOrdID]11=GHI|[OrdStatus]39=8[REJECTED]|[CxlRejResponseTo]434=2[ORDER_CANCELREPLACE_REQUEST]
[MsgType]35=9[ORDERCANCELREJECT]|[SenderCompID]49=SERVER|[TargetCompID]56=CLIENT|[OrigClOrdID]41=DEF|[ClOrdID]11=GHI
[MsgType]35=8[EXECUTIONREPORT]|[SenderCompID]49=SERVER|[TargetCompID]56=CLIENT|[ExecType]150=F[FILL]|[OrderID]37=123

=================================================================================
ORDER orderId:123 clOrdId:ABC
================================================================================
[MsgType]35=D[NEWORDERSINGLE]|[SenderCompID]49=CLIENT2|[TargetCompID]56=SERVER2|[ClOrdID]11=ABC
[MsgType]35=8[EXECUTIONREPORT]|[SenderCompID]49=SERVER2|[TargetCompID]56=CLIENT2|[ExecType]150=0[NEW]|[ClOrdID]11=ABC|[OrderID]37=123
[MsgType]35=8[EXECUTIONREPORT]|[SenderCompID]49=SERVER2|[TargetCompID]56=CLIENT2|[ExecType]150=F[FILL]|[ClOrdID]11=ABC|[OrderID]37=123
[MsgType]35=8[EXECUTIONREPORT]|[SenderCompID]49=SERVER2|[TargetCompID]56=CLIENT2|[ExecType]150=F[FILL]|[ClOrdID]11=ABC
[MsgType]35=8[EXECUTIONREPORT]|[SenderCompID]49=SERVER2|[TargetCompID]56=CLIENT2|[ExecType]150=F[FILL]|[OrderID]37=123
[MsgType]35=G[ORDERCANCELREPLACEREQUEST]|[SenderCompID]49=CLIENT2|[TargetCompID]56=SERVER2|[OrigClOrdID]41=ABC|[ClOrdID]11=DEF|[OrderID]37=123
[MsgType]35=8[EXECUTIONREPORT]|[SenderCompID]49=SERVER2|[TargetCompID]56=CLIENT2|[ExecType]150=F[FILL]|[OrderID]37=123
[MsgType]35=G[ORDERCANCELREPLACEREQUEST]|[SenderCompID]49=CLIENT2|[TargetCompID]56=SERVER2|[OrigClOrdID]41=DEF|[ClOrdID]11=GHI|[OrdStatus]39=8[REJECTED]|[CxlRejResponseTo]434=2[ORDER_CANCELREPLACE_REQUEST]
[MsgType]35=9[ORDERCANCELREJECT]|[SenderCompID]49=SERVER2|[TargetCompID]56=CLIENT2|[OrigClOrdID]41=DEF|[ClOrdID]11=GHI
[MsgType]35=8[EXECUTIONREPORT]|[SenderCompID]49=SERVER2|[TargetCompID]56=CLIENT2|[ExecType]150=F[FILL]|[OrderID]37=123
[MsgType]35=H[ORDERSTATUSREQUEST]|[SenderCompID]49=CLIENT2|[TargetCompID]56=SERVER2|[ClOrdID]11=GHI
[MsgType]35=8[EXECUTIONREPORT]|[SenderCompID]49=SERVER2|[TargetCompID]56=CLIENT2|[ExecType]150=I[ORDER_STATUS]|[OrderID]37=123
[MsgType]35=H[ORDERSTATUSREQUEST]|[SenderCompID]49=CLIENT2|[TargetCompID]56=SERVER2|[OrderID]37=123
[MsgType]35=8[EXECUTIONREPORT]|[SenderCompID]49=SERVER2|[TargetCompID]56=CLIENT2|[ExecType]150=I[ORDER_STATUS]|[OrderID]37=123
[MsgType]35=F[ORDERCANCELREQUEST]|[SenderCompID]49=CLIENT2|[TargetCompID]56=SERVER2|[ClOrdID]11=GHI
[MsgType]35=8[EXECUTIONREPORT]|[SenderCompID]49=SERVER2|[TargetCompID]56=CLIENT2|[ExecType]150=4[CANCELED]|[OrderID]37=123


ORPHAN MESSAGES:
[MsgType]35=9[ORDERCANCELREJECT]|[SenderCompID]49=SERVER2|[TargetCompID]56=CLIENT2|[OrigClOrdID]41=ORPHAN1|[ClOrdID]11=ORPHAN1
[MsgType]35=9[ORDERCANCELREJECT]|[SenderCompID]49=SERVER2|[TargetCompID]56=CLIENT2|[OrigClOrdID]41=ORPHAN2|[ClOrdID]11=ORPHAN2
[MsgType]35=8[EXECUTIONREPORT]|[SenderCompID]49=SERVER|[TargetCompID]56=CLIENT|[ExecType]150=F=123

FAQ

General

Is fixgrep free to use in a commercial environment

Yes. Fixgrep is released under the MIT licence which allows usage free-of-charge in a commercial environment.

Does fixgrep run under windows.

Yes. Fixgrep will run under any OS that has a JVM greater than or equal to Java 1.8. The most convenient way to run fixgrep is by using the fixgrep bash command. To run this under windows you will need to be running a bash prompt, e.g. cygwin. Currently there is no fixgrep.bat script written. At the moment I have no immediate intention to create one, but please feel free to submit a proposal.

Formatting

Why do I lose color formatting when piping fixgrep results to 'less'?

Indeed, some commands will not retain color formatting. For less, use the -R option

Performance

Can fixgrep be used as an alternative to grep when filtering large files.

It depends. Fixgrep will be much slower than grep, and will consume more CPU. For example running on my mac laptop, grep is roughly 5 times faster than fixgrep for searching for messages. If you don't want to wait too long and/or you are concerned about impact on CPU, best to use conventional grep commands to filter first and then pipe into fixgrep.

Can fixgrep be used as an alternative to 'more' or 'less' to view large FIX log files.

It depends. Applications such as 'more' or 'less' don't need to read an entire file during viewing. Whereas fixgrep does.
For large files (>100MB) it would be prudent to first extract the lines you wish to view (using grep or whatever), and pipe those lines into fixgrep.

How much memory does fixgrep use?

With one exception, fixgrep should not use much more than 64MB. Memory usage over time when parsing a large log file should not increase. The exception to this is when grouping by order. When grouping by order fixgrep will need to cache order messages before printing the out. This option is not enabled by default.

How much CPU does fixgrep use?

Fixgrep is a single threaded app, so at most it shouldn't use more than one core whilst it is running.

How can I reduce the impact on other existing processes whilst running fixgrep.

The regex which is run on each line to determine if the line is a fix message, and to capture the fix message is the single biggest CPU user in fixgrep. See the help for the input-line-format option for hints on how to make this fast.
Another way is to use the 'nice' command by specifying 'nice' before the 'fixgrep' script. e.g. 'nice fixgrep myfixlog.log' or 'cat myfixlog.log | nice fixgrep'
Nice takes a parameter which specifies how 'nice' you wish to be to other processes. Have a look at the nice man page for more info.

Licensing

Fixgrep is released under MIT license, a copy of which can be found here
This software is free to use/distribute/modify in both commercial and non-commercial environments.