'\" t
.\" Title: fex
.\" Author: [see the "AUTHOR(S)" section]
.\" Generator: Asciidoctor 2.0.16
.\" Date: 2021-08-03
.\" Manual: FEX
.\" Source: FEX
.\" Language: English
.\"
.TH "FEX" "1" "2021-08-03" "FEX" "FEX"
.ie \n(.g .ds Aq \(aq
.el .ds Aq '
.ss \n[.ss] 0
.nh
.ad l
.de URL
\fI\\$2\fP <\\$1>\\$3
..
.als MTO URL
.if \n[.g] \{\
. mso www.tmac
. am URL
. ad l
. .
. am MTO
. ad l
. .
. LINKSTYLE blue R < >
.\}
.SH "NAME"
fex \- simple and powerful field extraction
.SH "SYNOPSIS"
.sp
\fBfex\fP \fI<extract>...\fP
.SH "DESCRIPTION"
.sp
fex helps you split things by field. Common tasks you might do with awk or cut
are much simpler in fex, and there are things in fex you can\(cqt do nearly as easily
in awk or cut.
.SH "SELECTOR SYNTAX"
.sp
Extract syntax is one or more selectors, formatted as:
.sp
.if n .RS 4
.nf
.fam C
<delimiter><field number(s)|regexp>
.fam
.fi
.if n .RE
.sp
Fields start at 1, same as AWK. A field number of 0 selects the whole string,
unchanged.
.sp
You can specify multiple fields with curly braces and numbers split by commas.
Also valid in curly braces {} are number ranges. Number ranges are similar to
python array slices, split by colon.
.sp
The first delimiter is implied as space (\*(Aq \*(Aq), but can be overridden.
For example, to select the last dash\-separated field, you can use \f(CR\-\-1\fP.
.sp
A selector\(cqs field number(s) (or regexp) can be written in the following ways:
.sp
\fBa single number (field)\fP
.RS 4
.RE
.sp
A single number will select that numbered field. Like awk, field start at 1.
.sp
Example selecting third field:
.sp
.if n .RS 4
.nf
.fam C
% echo "a b c d e" | fex \*(Aq3\*(Aq
c
.fam
.fi
.if n .RE
.sp
Example selecting the second field delimited by slash:
.sp
.if n .RS 4
.nf
.fam C
% echo "/home/hello/world" | fex \*(Aq/2\*(Aq
hello
.fam
.fi
.if n .RE
.sp
\fB{N:M} (range)\fP
.RS 4
.RE
.sp
This is a range selection. The syntax for ranges is, in curly braces, N:M,
which chooses the fields in range N to M, inclusive.
.sp
Example selecting first through fourth fields:
.sp
.if n .RS 4
.nf
.fam C
% echo "a b c d e" | fex \*(Aq{1:4}\*(Aq
a b c d
.fam
.fi
.if n .RE
.sp
\fB{N,M,...} (field, field, ...)\fP
.RS 4
.RE
.sp
The syntax for multiple selections is numbers within curly braces.
.sp
Example selecting first and fifth fields:
.sp
.if n .RS 4
.nf
.fam C
% echo "a b c d e" | fex \*(Aq{1,5}\*(Aq
a e
.fam
.fi
.if n .RE
.sp
\fB{N:M,I,J,...} (range, field, field, ...)\fP
.RS 4
.RE
.sp
You can combine any of the above to select ranges and individual fields, in any
order, with the {...} syntax by delimiting each selection by a comma.
.sp
Example selecting fields 1 to 3, and 5: \f(CR{1:3,5}\fP
.sp
.if n .RS 4
.nf
.fam C
% echo "a b c d e" | fex \*(Aq{1:3,5}\*(Aq
a b c e
.fam
.fi
.if n .RE
.sp
\fB{<N:M} (reversed)\fP
.RS 4
.RE
.sp
The {<N:M} notation reverses the output of the fields N:M. This applies only to
N:M, so you can mix and match to reverse only a subset of fields. For example:
.sp
.if n .RS 4
.nf
.fam C
% echo 1 2 3 4 | fex \*(Aq{<1:\-2,\-1}\*(Aq
3 2 1 4
% echo 1 2 3 4 | fex \*(Aq{:,<:\-2}\*(Aq
1 2 3 4 3 2 1
.fam
.fi
.if n .RE
.sp
In the first example, it selects and reverses all but the last, then prints the
last field. In the second example, the fields are mirrored.
.sp
\fB{?...} (non\-greedy)\fP
.RS 4
.RE
.sp
The {?...} notation turns on \*(Aqnon greedy\*(Aq field separation. The differences here
can be shown best by example, first:
.sp
.if n .RS 4
.nf
.fam C
% echo "1...2.3.4" | fex \*(Aq.{1:3}\*(Aq
1.2.3
% echo "1...2.3.4" | fex \*(Aq.{?1:3}\*(Aq
1..
.fam
.fi
.if n .RE
.sp
In the first example, fex uses \*(Aq.\*(Aq as delimiter and ignores empty fields. In the
second example (non greedy), it does not ignore those empty fields.
.sp
\fB/regexp/ (regular expression)\fP
.RS 4
.RE
.sp
The /regexp/ selection will choose only fields that match the given pattern.
.sp
Example, pulling out words with \*(Aqaddr:\*(Aq in it from \*(Aqifconfig\*(Aq output:
.sp
.if n .RS 4
.nf
.fam C
% printf \*(Aq%s: addr:%s\(rsn\*(Aq lo0 127.0.0.1 en0 10.1.0.24 | fex \*(Aq /addr:[0\-9]/\*(Aq
addr:127.0.0.1
addr:10.1.0.24
.fam
.fi
.if n .RE
.sp
Regular expressions use RE2 syntax and are case\-sensitive by default. You can
read a reference for RE2 syntax at the site
.URL "https://github.com/google/re2/wiki/Syntax" "" ""
.SH "EXAMPLES"
.sp
\fBShow the MTU for a given interface\fP
.RS 4
.RE
.sp
The \*(AqMTU\*(Aq in \f(CRifconfig\fP output looks like \*(AqMTU:1500\*(Aq. So have fex split by
space, then grab fields matching /mtu:/, split by colon, and choose the last
field.
.sp
.if n .RS 4
.nf
.fam C
% ifconfig wlan0 | fex \*(Aq/MTU:/:\-1\*(Aq
1500
.fam
.fi
.if n .RE
.sp
\fBParse Apache logs\fP
.RS 4
.RE
.sp
Pull the IP address (first field by space) and the path requested (2nd field in
\*(AqGET <path> ...\*(Aq).
.sp
.if n .RS 4
.nf
.fam C
% fex 1 \*(Aq"2 2\*(Aq < /b/logs/access
65.57.245.11 /
65.57.245.11 /icons/blank.gif
65.57.245.11 /icons/folder.gif
.fam
.fi
.if n .RE
.SH "CONTACT"
.sp
You can file bugs, feature requests, or questions about the Go implementation at
the following URL:
.sp
.URL "https://todo.sr.ht/~nilium/tools" "" ""
.sp
Patches, discussion, ideas, issues, and so on are all welcome. Patches may be
emailed to ~nilium/public\-inbox@lists.sr.ht.
.sp
You can send any of the above by email to \c
.MTO "ncower\(atnil.dev" "" ""
if you\(cqre more
comfortable with that or would like your contact to remain private.
.SH "DISCUSSION"
.sp
The Go implementation began as an almost\-verbatim translation of the original C
to Go, with some modifications to adjust extract parsing to support selectors
like \f(CR\-\-1\fP or \f(CR\-{1}\fP as the initial selector in an abstract.
.sp
In addition, it isn\(cqt compatible with the original fex because it uses RE2 for
regular expressions instead of POSIX regular expressions. Many simple regular
expressions are still compatible, but if you used regular expressions heavily,
there may be some tricky pieces to it. For example, the original fex\(cqs regular
expressions are case\-insensitive while the Go implementation\(cqs are not.
.SH "SEE ALSO"
.sp
Related tools: \fBawk(1)\fP, \fBcut(1)\fP.
.sp
Project site: \c
.URL "https://git.sr.ht/~nilium/go\-fex" "" ""
.sp
Original C fex project site: \c
.URL "https://www.semicomplete.com/projects/fex" "" ""
.SH "AUTHORS"
.sp
fex was written by Jordan Sissel.
.sp
The Go implementation was written by Noel Cower.