~nilium/go-fex

ref: e053c8a133e0d433c83a5341a478f79020b35f17 go-fex/README.adoc -rw-r--r-- 5.1 KiB
e053c8a1 — Noel Cower Add a reverse flag for {<...} selectors 3 years ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
= fex(1)
:doctype: manpage
:manvolnum: 1
:manmanual: FEX
:mansource: FEX
:man-linkstyle: pass:[blue R < >]

// vim: set tw=80 sw=4 ts=4 et :

[[name]]
== Name

fex - simple and powerful field extraction

[[synopsis]]
== Synopsis

*fex* _<extract>..._

[[description]]
== Description

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't do nearly as easily
in awk or cut.

[[selector-syntax]]
== Selector Syntax

Extract syntax is one or more selectors, formatted as:

    <delimiter><field number(s)|regexp>

Fields start at 1, same as AWK. A field number of 0 selects the whole string,
unchanged.

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.

The first delimiter is implied as space (' '), but can be overridden.
For example, to select the last dash-separated field, you can use `--1`.

A selector's field number(s) (or regexp) can be written in the following ways:

*a single number (field)*::
--
A single number will select that numbered field. Like awk, field start at 1.

Example selecting third field:

    % echo "a b c d e" | fex '3'
    c

Example selecting the second field delimited by slash:

    % echo "/home/hello/world" | fex '/2'
    hello
--

*{N:M} (range)*::
--
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.

Example selecting first through fourth fields:

    % echo "a b c d e" | fex '{1:4}'
    a b c d
--

*{N,M,...} (field, field, ...)*::
--
The syntax for multiple selections is numbers within curly braces.

Example selecting first and fifth fields:

    % echo "a b c d e" | fex '{1,5}'
    a e
--

*{N:M,I,J,...} (range, field, field, ...)*::
--
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.

Example selecting fields 1 to 3, and 5: `{1:3,5}`

    % echo "a b c d e" | fex '{1:3,5}'
    a b c e
--

*{<M:N} (reversed)*::
--
The {<M:N} notation reverses the output of the fields M:N. This applies only to
N:M, so you can mix and match to reverse only a subset of fields. For example:

    % echo 1 2 3 4 | fex '{<1:-2,-1}'
    3 2 1 4
    % echo 1 2 3 4 | fex '{:,<:-2}'
    1 2 3 4 3 2 1

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

*{?...} (non-greedy)*::
--
The {?...} notation turns on 'non greedy' field separation. The differences here
can be shown best by example, first:

    % echo "1...2.3.4" | fex '.{1:3}'
    1.2.3
    % echo "1...2.3.4" | fex '.{?1:3}'
    1..

In the first example, fex uses '.' as delimiter and ignores empty fields. In the
second example (non greedy), it does not ignore those empty fields.
--

*/regexp/ (regular expression)*::
--
The /regexp/ selection will choose only fields that match the given pattern.

Example, pulling out words with 'addr:' in it from 'ifconfig' output:

    % printf '%s: addr:%s\n' lo0 127.0.0.1 en0 10.1.0.24 | fex ' /addr:[0-9]/'
    addr:127.0.0.1
    addr:10.1.0.24

Regular expressions use RE2 syntax and are case-sensitive by default. You can
read a reference for RE2 syntax at the site
link:https://github.com/google/re2/wiki/Syntax[]
--

[[examples]]
== Examples

*Show the MTU for a given interface*::
--
The 'MTU' in `ifconfig` output looks like 'MTU:1500'. So have fex split by
space, then grab fields matching /mtu:/, split by colon, and choose the last
field.

    % ifconfig wlan0 | fex '/MTU:/:-1'
    1500
--

*Parse Apache logs*::
--
Pull the IP address (first field by space) and the path requested (2nd field in
'GET <path> ...').

    % fex 1 '"2 2' < /b/logs/access
    65.57.245.11 /
    65.57.245.11 /icons/blank.gif
    65.57.245.11 /icons/folder.gif
--

[[contact]]
== Contact

You can file bugs, feature requests, or questions about the Go implementation at
the following URL:

link:https://github.com/nilium/go-fex/issues[]

Patches, discussion, ideas, issues, and so on are all welcome.

You can send any of the above by email to ncower@gmail.com if you're more
comfortable with that.

[[notes]]
== Discussion

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 `--1` or `-{1}` as the initial selector in an abstract.

In addition, it isn't 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's regular
expressions are case-insensitive while the Go implementation's are not.

[[see-also]]
== See Also

Related tools: *awk(1)*, *cut(1)*.

Project site: link:https://github.com/nilium/go-fex[]

Original C fex project site: link:https://www.semicomplete.com/projects/fex[]

[[author]]
== Authors

fex was written by Jordan Sissel.

The Go implementation was written by Noel Cower.