<article>
<h2 id="introduction">Introduction</h2>
<p>I have occasionally been using a tool called <code>ack</code> for a
few years now. It’s billed as <em>“an alternative to grep for
programmers”</em>.</p>
<p>There are several features I find particularly useful:</p>
<ul>
<li><p>It can restrict text searches to files of a particular
<em>type</em></p></li>
<li><p>It uses Perl regular expressions which may be the most powerful
and feature rich types of RE’s available at present</p></li>
<li><p>You can limit the search area within a file if desired</p></li>
</ul>
<p>It is a very comprehensive and useful tool, though maybe quite
complex to use. Personally I use it in special cases where I need its
power, and otherwise use the usual <code>grep</code>.</p>
<p>In this episode I will give you the flavour of its capabilities and
otherwise leave you to research more if it sounds interesting.</p>
<h2 id="installing-ack">Installing <code>ack</code></h2>
<p>The tool can be found in repositories. I use Debian, and
<code>ack</code> is in the Debian repo and can be installed with:</p>
<pre><code>sudo apt install ack</code></pre>
<p>Installing it this way the version I have (and am describing here) is
3.6.0. There is a new version, 3.7.0 available from the <a
href="https://beyondgrep.com/">website</a>.</p>
<p>The documentation on the website suggests installing it as a Perl
module using <code>CPAN</code>, which is something I will do soon I
think.</p>
<h2 id="perl-regular-expressions">Perl regular expressions</h2>
<p>These are very sophisticated.</p>
<p>A project to convert the Perl regular expression capabilities into a
portable library form was undertaken by Philip Hazel of Cambridge
University in 1997, and was called <em>Perl Compatible Regular
Expressions</em> or PCRE.</p>
<p>Philip Hazel was the originator of the <code>exim</code> mail
transfer agent (MTA, or mail server), and wanted to use PCRE within
it.</p>
<p>Since then PCRE (and later PCRE2) is the way regular expressions are
implemented in a lot of other software, which shows how widespread use
of the Perl RE has become.</p>
<p>The <code>ack</code> documentation refers to the Perl manual for
details of this type of regular expression, and to a tutorial, if you
wish to gain a deeper understanding.</p>
<p>It should be noted that GNU <code>grep</code> can use Perl compatible
regular expressions when matching lines in files, but this feature is
marked as experimental.</p>
<h2 id="file-types">File types</h2>
<p>The <code>ack</code> command has rules for recognising file types. It
does this by looking at the name extensions (<code>'.html'</code> or
<code>'.py'</code> for example), and in some cases by examining their
contents. The complete list of types can be found by running:</p>
<pre><code>ack --help-types</code></pre>
<p>… or, for a more detailed but less readable list:</p>
<pre><code>ack --dump</code></pre>
<p>Some examples are:</p>
<ul>
<li><code>cc</code> for C files</li>
<li><code>haskell</code> for Haskell files</li>
<li><code>lua</code> for Lua files</li>
<li><code>python</code> for Python files</li>
<li><code>shell</code> for Bash, and other shell command files</li>
</ul>
<p>These names can be used with the options <code>-t TYPE</code> and
<code>--type=TYPE</code> and also by simply preceding them with two
dashes (<code>--TYPE</code>). There are also ways of requesting files
not of a given type: <code>-T TYPE</code>, <code>--type=noTYPE</code>
and <code>--noTYPE</code>.</p>
<p>To check files in the current directory of type <code>shell</code> an
<code>ack</code> command like the following might be used and the
following type of output produced:</p>
<pre><code>$ ack --shell declare
Bash_snippet__using_coproc_with_SQLite/examples/coproc_test.sh
11:declare -a com=(&#39;date +%F&#39; &#39;whoami&#39; &#39;id&#39; &#39;echo &quot;$BASH_VERSION&quot;&#39;</code></pre>
<p>Note that <code>ack</code> reports the file path and numbered lines
within it that match.</p>
<p>You can add your own file types to <code>ack</code>. There is a
configuration file called <code>.ackrc</code> in which new types can be
declared. See below for more information.</p>
<p>The file type feature is one that makes me use <code>ack</code> again
and again.</p>
<h2 id="the-.ackrc-file">The <code>.ackrc</code> file</h2>
<p>This file contains <em>“command-line options that are prepended to
the command line before processing”</em>.</p>
<p>It’s a useful way to add new types (or even modify existing
ones).</p>
<p>It can be located in a number of places. Mine is
<code>~/.ackrc</code> with other configuration files in my home
directory.</p>
<p>It’s possible to generate a new <code>.ackrc</code> with the option
<code>--create-ackrc</code>. This saves all the default settings in the
file which makes it simple to adjust anything you need to change.</p>
<p>As an example of a change, I have Markdown files with the extension
<code>.mkd</code>. However, by default <code>ack</code> only recognises
<code>.md</code>, and <code>.markdown</code>. To add <code>.mkd</code>
to the list I can add one of the following to the
<code>.ackrc</code>:</p>
<pre><code># Either add `.mkd` to the list
--type-add=markdown:ext:mkd
# or replace the list with a new one
--type-set=markdown:ext:md,mkd,markdown</code></pre>
<p>Note that lines beginning with <code>#</code> are comments. Note also
that <code>--type-add</code> and <code>--type-set</code> have to be
followed by an <code>=</code> sign, not a space in this file.</p>
<p>If you examine the settings with <code>ack --dump</code> you will see
the default command and the one you have added. If you use
<code>ack --help-types</code> you will see the new extension added to
the default list.</p>
<pre><code>markdown     .md .markdown; .mkd</code></pre>
<p>If I use this to search files in the directory where I keep my HPR
episodes I see:</p>
<pre><code>$ ack --markdown &#39;inner ear&#39;
Hacking_my_inner_ear/hpr2109_full_shownotes.mkd
24:became fascinated by the structure of the human [inner ear][2], and studied it
28:The human inner ear performs two major functions:
.
.
.</code></pre>
<h2 id="quick-review-of-selected-ack-options">Quick review of selected
<code>ack</code> options</h2>
<h3 id="usage">Usage</h3>
<p>The <code>ack</code> command is designed to be similar in as many
respects as possible to <code>grep</code>. The command is used in
general as follows:</p>
<pre><code>ack [OPTION]... PATTERN [FILES OR DIRECTORIES]</code></pre>
<p>The <code>[OPTION]</code> part denotes any options (some discussed
below) and <code>PATTERN</code> is the PCRE search pattern. There are
some cases where this must be omitted - such as when files of a
particular type are being listed. See example 1 below for such a
case.</p>
<p>In some cases a particular file is being searched, or all files in
certain directories, and that is what
<code>[FILES OR DIRECTORIES]</code> denotes.</p>
<p>The full documentation for <code>ack</code> can be seen with the
usual <code>man ack</code> command, and also using
<code>ack --man</code>. There is also an option <code>--help</code>
which gives a summary of all of the available options.</p>
<h3 id="options">Options</h3>
<p>There are many options specific to <code>ack</code> and some in
common with <code>grep</code>, and we’ll look at just a few here:</p>
<ul>
<li><p><code>-i</code> - like <code>grep</code> this makes the matched
pattern case insensitive.</p></li>
<li><p><code>-f</code> - Only print the files that would be searched,
without actually doing any searching. See example 1 below.</p></li>
<li><p><code>-g</code> - Same as -f, but only select files whose names
match PATTERN. This interacts with file type searches like
<code>--html</code>, so beware.</p></li>
<li><p><code>-l</code> - reports the file names which contain matches
for a given pattern</p></li>
<li><p><code>-L</code> - reports the file names which <em>do not</em>
contain matches for a given pattern</p></li>
<li><p><code>-c</code> - reports file names and the number of matches;
used on its own it reports <em>all</em> files, those that match and
those that do not. If used with <code>-l</code> then you only see the
names of file that have matches, as well as a count of matches. See
example 2 below.</p></li>
<li><p><code>-w</code> - forces the search pattern to match only whole
words. See example 3 below. (Note: there is an equivalent in GNU grep,
which I had not checked when I recorded the audio).</p></li>
</ul>
<h2 id="examples">Examples</h2>
<h3 id="find-all-markdown-files-in-a-directory">1. Find all Markdown
files in a directory</h3>
<p>Using the <code>-f</code> option:</p>
<pre><code>$ ack --markdown -f Nitecore_Tube_torch/
Nitecore_Tube_torch/README.mkd
Nitecore_Tube_torch/container.mkd
Nitecore_Tube_torch/index.mkd
Nitecore_Tube_torch/shownotes.mkd</code></pre>
<p>Using the <code>-g</code> option:</p>
<pre><code>$ ack -g &#39;&bsol;.mkd$&#39; Nitecore_Tube_torch/
Nitecore_Tube_torch/README.mkd
Nitecore_Tube_torch/container.mkd
Nitecore_Tube_torch/index.mkd
Nitecore_Tube_torch/shownotes.mkd</code></pre>
<h3 id="names-of-files-that-contain-a-match-with-a-match-count">2. Names
of files that contain a match, with a match count</h3>
<p>Using the <code>-l</code> and <code>-c</code> options:</p>
<pre><code>$ ack --markdown -lci &#39;&bsol;bear&bsol;b&#39;
Hacking_my_inner_ear/hpr2109_full_shownotes.mkd:11
Hacking_my_inner_ear/shownotes.mkd:3
An_overview_of_the_ack_command/shownotes.mkd:6</code></pre>
<p>The sequence <code>'&bsol;b'</code> in Perl regular expressions is a
boundary such as a word boundary. So the pattern is looking for the word
<code>'ear'</code> as opposed to the characters <code>'ear'</code> (as
in <code>'pearl'</code> for example).</p>
<p>Note how the single-letter options <code>-l</code>, <code>-c</code>
and <code>-i</code> can be concatenated.</p>
<h3 id="searching-for-words-in-a-simpler-way">3. Searching for words in
a simpler way</h3>
<p>In example 2 the <code>&bsol;b</code> boundaries ensured the pattern
matched words rather than letter sequences. This can be simplified by
using the <code>-w</code> option:</p>
<pre><code>$ ack --markdown -lci -w &#39;ear&#39;
Hacking_my_inner_ear/hpr2109_full_shownotes.mkd:11
Hacking_my_inner_ear/shownotes.mkd:3
An_overview_of_the_ack_command/shownotes.mkd:6</code></pre>
<h2 id="links">Links</h2>
<ul>
<li>The <code>ack</code> website:
<ul>
<li><a href="https://beyondgrep.com/">ack!</a></li>
</ul></li>
</ul>
<ul>
<li>Perl regular expressions:
<ul>
<li><a href="https://perldoc.perl.org/perlreref.html">RE reference
manual</a></li>
<li><a href="https://perldoc.perl.org/perlretut.html">RE
tutorial</a></li>
</ul></li>
</ul>
<ul>
<li>PCRE: <em>Perl Compatible Regular Expressions</em>:
<ul>
<li><a
href="https://en.wikipedia.org/wiki/Perl_Compatible_Regular_Expressions">Wikipedia
article on PCRE</a></li>
<li><a href="https://en.wikipedia.org/wiki/Philip_Hazel">Wikipedia
article on Philip Hazel</a></li>
</ul></li>
</ul>
</article>
