<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="../feed.xsl" type="text/xsl"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Susam's Unix Pages</title>
  <subtitle>Feed for Susam's Unix Pages</subtitle>
  <link href="https://susam.net/"/>
  <link href="https://susam.net/tag/unix.xml" rel="self"/>
  <id>https://susam.net/tag/unix.xml</id>
  <updated>2025-04-05T00:00:00Z</updated>
  <author><name>Susam Pal</name></author>
  <entry>
    <title>Hacker News Hug of Deaf</title>
    <link href="https://susam.net/hn-bell.html"/>
    <id>urn:uuid:94fda865-ecac-4354-a570-4e6fd18db614</id>
    <updated>2025-04-05T00:00:00Z</updated>
    <content type="html">
<!-- BEGIN HTML -->
&lt;blockquote&gt;
  &lt;p&gt;
    &quot;It&apos;s essentially the Hacker News Hug of Deaf.&quot;
    &amp;ndash;
    &lt;a href=&quot;https://news.ycombinator.com/item?id=30146019#30147639&quot;&gt;@TonyTrapp&lt;/a&gt;
  &lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;
  About three years ago, I set up a tiny &lt;code&gt;netcat&lt;/code&gt; loop on
  one of my Debian servers to accept arbitrary connections from the
  Hacker News (HN) community.  The loop ran for 24 hours and did
  exactly three things whenever a client connected:
&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;
    Send a simple &lt;code&gt;ok&lt;/code&gt; message to the client.
  &lt;/li&gt;
  &lt;li&gt;
    Close the connection immediately.
  &lt;/li&gt;
  &lt;li&gt;
    Make my terminal beep four times.
  &lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;
  That&apos;s it!  It was a playful experiment in response to a thread
  about quirky, do-it-yourself alerting systems for friends and
  family.  See
  &lt;a href=&quot;https://news.ycombinator.com/item?id=30146019#30146451&quot;&gt;this
  HN thread&lt;/a&gt; for the original discussion.  Here is the exact
  command I ran on my server:
&lt;/p&gt;
&lt;pre class=&quot;wrap&quot;&gt;&lt;code&gt;while true; do (echo ok | nc -q 1 -vlp 8000 2&amp;gt;&amp;amp;1; echo; date -u) | tee -a beeper.log; for i in 1 2 3 4; do printf &apos;\a&apos;; sleep 1; done &amp;amp; done&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
  The &lt;code&gt;nc&lt;/code&gt; command closes the connection immediately after
  sending the &lt;code&gt;ok&lt;/code&gt; message and runs an
  inner &lt;code&gt;for&lt;/code&gt; loop in a background shell that
  asynchronously prints the bell character to the terminal four times.
  Meanwhile, the outer &lt;code&gt;while&lt;/code&gt; command loops back quickly
  to run a new &lt;code&gt;nc&lt;/code&gt; process, thus making this one-liner
  script instantly ready to accept the next incoming connection.
&lt;/p&gt;
&lt;p&gt;
  Soon after I shared this, members of the HN community began
  connecting to the demo running on &lt;code&gt;susam.net:8000&lt;/code&gt;.
  Anyone on the Internet could use any client of their choice to
  connect.  Here&apos;s how I explained it in the HN thread:
&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;
    Now anytime someone connects to port 8000 of my system
    by &lt;em&gt;any&lt;/em&gt; means, I will hear 4 beeps!  The other party can
    use &lt;em&gt;whatever client&lt;/em&gt; they have to connect to port 8000 of
    my system, e.g. a web browser, &lt;code&gt;nc HOST
    8000&lt;/code&gt;, &lt;code&gt;curl HOST:8000&lt;/code&gt; or even &lt;code&gt;ssh HOST -p
    8000&lt;/code&gt;, &lt;code&gt;irssi -c HOST -p 8000&lt;/code&gt;, etc.
  &lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;
  In the next 24 hours, I received over 4761 connections, each one
  triggering four beeps.  That&apos;s a total of 19&amp;#x202f;044 terminal
  beeps echoing throughout the day!
&lt;/p&gt;
&lt;figure class=&quot;soft&quot;&gt;
  &lt;img src=&quot;files/blog/beeper1.png&quot; alt=&quot;Graph&quot;&gt;
  &lt;figcaption&gt;
    Number of connections received every hour since 31 Jan 2022 10:00 UTC
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
  The data for the above graph is available at
  &lt;a href=&quot;https://gist.github.com/susam/159c7d92659b3185eb0b0d683998a3b7&quot;&gt;beeper.log&lt;/a&gt;.
  Now, 4761 isn&apos;t a huge number in the grand scheme of things, but it
  was still pretty cool to see people notice an obscure comment buried
  in a regular HN thread, act on it and make my terminal beep
  thousands of time.
&lt;/p&gt;
&lt;p&gt;
  At the end of the day, this was a fun experiment.  Pointless, but
  fun!  Computing isn&apos;t always about solving problems.  Sometimes,
  it&apos;s also about exploring quirky ideas.  The joy is in the
  exploration and having others join in made it even more enjoyable.
  Activities like this keep computing fun for me!
&lt;/p&gt;
&lt;hr&gt;
&lt;p id=&quot;update-2025-04-10&quot;&gt;
  &lt;strong&gt;Update on 10 Apr 2025:&lt;/strong&gt;
  I &lt;a href=&quot;https://news.ycombinator.com/item?id=43642123&quot;&gt;shared
  this article on Hacker News&lt;/a&gt; today and saw another surge in
  connections to my beeper loop.
&lt;/p&gt;
&lt;figure class=&quot;soft&quot;&gt;
  &lt;img src=&quot;files/blog/beeper2.png&quot; alt=&quot;Graph&quot;&gt;
  &lt;figcaption&gt;
    Number of connections received every hour since 10 Apr 2025 10:00 UTC
  &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;
  The data for the above graph is available at
  &lt;a href=&quot;https://gist.github.com/susam/3cec5db1a78a9db527327460656daeae&quot;&gt;beeper2.log&lt;/a&gt;.
  The data shows a total of 352&amp;#x202f;831 connections from 1396
  unique client addresses over 14 hours.  That amounts to a total of
  1&amp;#x202f;411&amp;#x202f;324 beeps!  Much of the traffic seems to have
  come from persistent client loops constantly connecting to my beeper
  loop.  In particular, the client identified by the anonymised
  identifier C0276 made the largest number of connections by far, with
  327&amp;#x202f;209 total connections.  The second most active client,
  C0595, made only 6771 connections.  There were 491 clients that
  connected exactly once.  If you&apos;d like to see the number of
  connections by each client, see
  &lt;a href=&quot;https://gist.github.com/susam/d6766f4b722f899250a8f3da0c98f993&quot;&gt;beeperclient2.log&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
  In conclusion, the difference in the volume of connections between
  the earlier experiment and today&apos;s is striking.  In the first round,
  three years ago, there were only 4761 connections from some readers
  of a comment thread.  But in today&apos;s round, with this post being
  featured on the HN front page, there were 352&amp;#x202f;831
  connections!  It is fascinating to see how odd experiments like this
  can find so many participants within the HN community!
&lt;/p&gt;
<!-- ### -->
&lt;p&gt;
  &lt;a href="https://susam.net/hn-bell.html"&gt;Read on website&lt;/a&gt; |
  &lt;a href=&quot;https://susam.net/tag/absurd.html&quot;&gt;#absurd&lt;/a&gt; |
  &lt;a href=&quot;https://susam.net/tag/unix.html&quot;&gt;#unix&lt;/a&gt; |
  &lt;a href=&quot;https://susam.net/tag/shell.html&quot;&gt;#shell&lt;/a&gt; |
  &lt;a href=&quot;https://susam.net/tag/networking.html&quot;&gt;#networking&lt;/a&gt; |
  &lt;a href=&quot;https://susam.net/tag/technology.html&quot;&gt;#technology&lt;/a&gt;
&lt;/p&gt;
<!-- END HTML -->
    </content>
  </entry>
  <entry>
    <title>Pretty-Printing JSON Response with HTTP Headers</title>
    <link href="https://susam.net/pretty-print-json-response-with-http-headers.html"/>
    <id>urn:uuid:894ff191-0b1a-454a-8757-7aa3a94b94f2</id>
    <updated>2024-04-14T00:00:00Z</updated>
    <content type="html">
<!-- BEGIN HTML -->
&lt;p&gt;
  Often while using &lt;code&gt;curl&lt;/code&gt; with URLs that return a JSON
  response, I need to print the HTTP response headers along with the
  JSON response.  Here is an example that shows how this can be done:
&lt;/p&gt;
&lt;pre&gt;&lt;samp&gt;$ &lt;kbd&gt;curl -sSi https://susam.net/code/lab/json/books.json&lt;/kbd&gt;
HTTP/1.1 200 OK
Server: nginx/1.18.0
Date: Sat, 05 Apr 2024 11:53:24 GMT
Content-Type: application/json
Content-Length: 172
Last-Modified: Sat, 05 Apr 2024 11:53:05 GMT
Connection: keep-alive
ETag: &quot;67f119a1-ac&quot;
Accept-Ranges: bytes

[
  {&quot;title&quot;: &quot;Gulliver&apos;s Travels&quot;, &quot;author&quot;: &quot;Jonathan Swift&quot;, &quot;published&quot;: 1726},
  {&quot;title&quot;: &quot;Treasure Island&quot;, &quot;author&quot;: &quot;Robert Louis Stevenson&quot;, &quot;published&quot;: 1883}
]&lt;/samp&gt;&lt;/pre&gt;
&lt;p&gt;
  The above output is obtained using curl 7.77.0
  (x86_64-apple-darwin21.0).  The &lt;code&gt;-i&lt;/code&gt; option is
  responsible for including the HTTP response headers.
  The &lt;code&gt;-s&lt;/code&gt; and &lt;code&gt;-S&lt;/code&gt; options are not too
  important for the current discussion but I usually happen to use
  them out of habit.  The &lt;code&gt;-s&lt;/code&gt; option suppresses the
  progress meter and error messages but the &lt;code&gt;-S&lt;/code&gt; re-enables
  the display of error messages.  This helps me avoid the progress
  meter in the output without having to lose visibility of any errors
  that may arise.
&lt;/p&gt;
&lt;p&gt;
  So far so good!  But can we also have the JSON response
  pretty-printed with say &lt;code&gt;jq&lt;/code&gt;?  The above command prints
  both the HTTP headers and the response to the standard output, so
  piping the standard output to &lt;code&gt;jq&lt;/code&gt; does not work.
  The &lt;code&gt;jq&lt;/code&gt; command fails with an error as soon as it
  encounters the HTTP headers.
&lt;/p&gt;
&lt;p&gt;
  If, however, we manage to send the HTTP header and the response to
  different streams or files, then we could utilise &lt;code&gt;jq&lt;/code&gt; to
  pretty-print the stream or file that contains the JSON response.
  Here is an example that shows how to do this:
&lt;/p&gt;
&lt;pre&gt;&lt;samp&gt;$ &lt;kbd&gt;curl -sSD head.txt -o out.json https://susam.net/code/lab/json/books.json &amp;amp;&amp;amp; cat head.txt &amp;amp;&amp;amp; jq . out.json&lt;/kbd&gt;
HTTP/1.1 200 OK
Server: nginx/1.18.0
Date: Sat, 05 Apr 2024 11:53:51 GMT
Content-Type: application/json
Content-Length: 172
Last-Modified: Sat, 05 Apr 2024 11:53:05 GMT
Connection: keep-alive
ETag: &quot;67f119a1-ac&quot;
Accept-Ranges: bytes

[
  {
    &quot;title&quot;: &quot;Gulliver&apos;s Travels&quot;,
    &quot;author&quot;: &quot;Jonathan Swift&quot;,
    &quot;published&quot;: 1726
  },
  {
    &quot;title&quot;: &quot;Treasure Island&quot;,
    &quot;author&quot;: &quot;Robert Louis Stevenson&quot;,
    &quot;published&quot;: 1883
  }
]&lt;/samp&gt;&lt;/pre&gt;
&lt;p&gt;
  Alternatively, we can achieve this using a single command by
  printing the the HTTP headers to standard error.  This ensures that
  only the JSON response is printed to standard output, which we can
  then pretty-print using &lt;code&gt;jq&lt;/code&gt;.  Here is an example:
&lt;/p&gt;
&lt;pre&gt;&lt;samp&gt;$ &lt;kbd&gt;curl -sSD /dev/stderr https://susam.net/code/lab/json/books.json | jq .&lt;/kbd&gt;
HTTP/1.1 200 OK
Server: nginx/1.18.0
Date: Sat, 05 Apr 2024 11:54:12 GMT
Content-Type: application/json
Content-Length: 172
Last-Modified: Sat, 05 Apr 2024 11:53:05 GMT
Connection: keep-alive
ETag: &quot;67f119a1-ac&quot;
Accept-Ranges: bytes

[
  {
    &quot;title&quot;: &quot;Gulliver&apos;s Travels&quot;,
    &quot;author&quot;: &quot;Jonathan Swift&quot;,
    &quot;published&quot;: 1726
  },
  {
    &quot;title&quot;: &quot;Treasure Island&quot;,
    &quot;author&quot;: &quot;Robert Louis Stevenson&quot;,
    &quot;published&quot;: 1883
  }
]&lt;/samp&gt;&lt;/pre&gt;
<!-- ### -->
&lt;p&gt;
  &lt;a href="https://susam.net/pretty-print-json-response-with-http-headers.html"&gt;Read on website&lt;/a&gt; |
  &lt;a href=&quot;https://susam.net/tag/unix.html&quot;&gt;#unix&lt;/a&gt; |
  &lt;a href=&quot;https://susam.net/tag/shell.html&quot;&gt;#shell&lt;/a&gt; |
  &lt;a href=&quot;https://susam.net/tag/networking.html&quot;&gt;#networking&lt;/a&gt; |
  &lt;a href=&quot;https://susam.net/tag/technology.html&quot;&gt;#technology&lt;/a&gt;
&lt;/p&gt;
<!-- END HTML -->
    </content>
  </entry>
  <entry>
    <title>Control, Escape and Meta Tricks</title>
    <link href="https://susam.net/control-escape-meta-tricks.html"/>
    <id>urn:uuid:bbe73d4e-8b02-4fb2-b3c2-b765c3e129a6</id>
    <updated>2023-06-16T00:00:00Z</updated>
    <content type="html">
<!-- BEGIN HTML -->
&lt;h2 id=&quot;terminal-tricks&quot;&gt;Terminal Tricks&lt;/h2&gt;
&lt;p&gt;
  Open a Unix or Linux terminal emulator.  If you have Terminal.app on
  macOS, ensure that the &quot;Use Option as Meta Key&quot; option is enabled in
  its &quot;Preferences&quot; section.  Now type &lt;code&gt;foo bar baz&lt;/code&gt;
  followed by &lt;kbd&gt;meta&lt;/kbd&gt;+&lt;kbd&gt;b&lt;/kbd&gt;
  (i.e. &lt;kbd&gt;alt&lt;/kbd&gt;+&lt;kbd&gt;b&lt;/kbd&gt; or &lt;kbd&gt;option&lt;/kbd&gt;+&lt;kbd&gt;b&lt;/kbd&gt;
  on modern keyboards).  In a typical desktop environment with a
  typical and modern terminal emulator running a modern shell like
  Bash, Zsh, etc., the cursor should move backward by one word.  Now
  type &lt;kbd&gt;esc&lt;/kbd&gt; &lt;kbd&gt;b&lt;/kbd&gt;.  The cursor should move back again
  by one word.  Finally type &lt;kbd&gt;ctrl&lt;/kbd&gt;+&lt;kbd&gt;[&lt;/kbd&gt; &lt;kbd&gt;b&lt;/kbd&gt;
  and the same thing should happen again.  How are we able to perform
  the same operation in three different ways?
&lt;/p&gt;
&lt;p&gt;
  Note that if the desktop environment or the terminal emulator or the
  set of shell key bindings is configured differently, the results may
  vary.  But we will assume that the typical defaults are in effect in
  the remainder of this post.  To understand why these three key
  sequences yield the same result, it might be a good exercise to run
  the command &lt;code&gt;cat&lt;/code&gt; and type the three key sequences again.
  The three key sequences we are talking about are:
&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;
    &lt;kbd&gt;meta&lt;/kbd&gt;+&lt;kbd&gt;b&lt;/kbd&gt; (i.e. &lt;kbd&gt;alt&lt;/kbd&gt;+&lt;kbd&gt;b&lt;/kbd&gt;
    or &lt;kbd&gt;option&lt;/kbd&gt;+&lt;kbd&gt;b&lt;/kbd&gt; on modern keyboards)
  &lt;/li&gt;
  &lt;li&gt;
    &lt;kbd&gt;esc&lt;/kbd&gt; &lt;kbd&gt;b&lt;/kbd&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;kbd&gt;ctrl&lt;/kbd&gt;+&lt;kbd&gt;[&lt;/kbd&gt; &lt;kbd&gt;b&lt;/kbd&gt;
  &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
  When we run &lt;code&gt;cat&lt;/code&gt; and type the three key sequences
  mentioned above, the following output may appear:
&lt;/p&gt;
&lt;pre&gt;&lt;samp&gt;$ &lt;kbd&gt;cat
^[b^[b^[b&lt;/kbd&gt;&lt;/samp&gt;&lt;/pre&gt;
&lt;p&gt;
  The output shows that the terminal sends the same input
  to &lt;code&gt;cat&lt;/code&gt; each time: the &lt;em&gt;escape&lt;/em&gt; character that
  appears as &lt;code&gt;^[&lt;/code&gt; in the output and the
  character &lt;code&gt;b&lt;/code&gt;.  This becomes more apparent if instead of
  running &lt;code&gt;cat&lt;/code&gt;, we run &lt;code&gt;od -t d1&lt;/code&gt; and type the
  three key sequences followed
  by &lt;kbd&gt;ctrl&lt;/kbd&gt;+&lt;kbd&gt;d&lt;/kbd&gt; &lt;kbd&gt;enter&lt;/kbd&gt;:
&lt;/p&gt;
&lt;pre&gt;&lt;samp&gt;$ &lt;kbd&gt;od -t d1
^[b^[b^[b&lt;/kbd&gt;
0000000    27  98  27  98  27  98  10
0000007&lt;/samp&gt;&lt;/pre&gt;
&lt;p&gt;
  Indeed decimal 27 is the code of the &lt;em&gt;escape&lt;/em&gt; character.
  Similarly decimal 98 is the code of the character &lt;code&gt;b&lt;/code&gt;.
&lt;/p&gt;
&lt;h2 id=&quot;control-codes&quot;&gt;Control Codes&lt;/h2&gt;
&lt;p&gt;
  Let us first discuss why typing &lt;kbd&gt;ctrl&lt;/kbd&gt;+&lt;kbd&gt;[&lt;/kbd&gt;
  produces the &lt;em&gt;escape&lt;/em&gt; character.  The
  character &lt;code&gt;[&lt;/code&gt; has code 91 (binary 1011011) and holding
  the &lt;kbd&gt;ctrl&lt;/kbd&gt; key while typing it results in a control code
  obtained by taking 91 (binary 1011011), keeping its five least
  significant bits and discarding the rest.  We get the control code
  27 (binary 11011) as the result.  This is the code of
  the &lt;em&gt;escape&lt;/em&gt; character.  This explains
  why &lt;kbd&gt;ctrl&lt;/kbd&gt;+&lt;kbd&gt;[&lt;/kbd&gt; produces the &lt;em&gt;escape&lt;/em&gt;
  character and why the &lt;em&gt;escape&lt;/em&gt; character is represented
  as &lt;code&gt;^[&lt;/code&gt; while typing it into the standard input.  The
  caret sign (&lt;code&gt;^&lt;/code&gt;) here is a notation for
  the &lt;code&gt;ctrl&lt;/code&gt; modifier.
&lt;/p&gt;
&lt;p&gt;
  The following table provides some more examples of control codes
  that can be obtained by typing the &lt;kbd&gt;ctrl&lt;/kbd&gt; key along with
  some other key.
&lt;/p&gt;
&lt;table class=&quot;grid mono&quot;&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th rowspan=&quot;2&quot;&gt;Key&lt;/th&gt;
      &lt;th colspan=&quot;3&quot;&gt;Modified Character&lt;/th&gt;
      &lt;th colspan=&quot;3&quot;&gt;Control Character&lt;/th&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;Binary&lt;/th&gt;
      &lt;th&gt;Decimal&lt;/th&gt;
      &lt;th&gt;Character&lt;/th&gt;
      &lt;th&gt;Binary&lt;/th&gt;
      &lt;th&gt;Decimal&lt;/th&gt;
      &lt;th&gt;Character&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;ctrl&lt;/kbd&gt;+&lt;kbd&gt;@&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;1000000&lt;/td&gt;
      &lt;td&gt;64&lt;/td&gt;
      &lt;td&gt;@&lt;/td&gt;
      &lt;td&gt;00000&lt;/td&gt;
      &lt;td&gt;0&lt;/td&gt;
      &lt;td&gt;Null&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;ctrl&lt;/kbd&gt;+&lt;kbd&gt;g&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;1000111&lt;/td&gt;
      &lt;td&gt;71&lt;/td&gt;
      &lt;td&gt;G&lt;/td&gt;
      &lt;td&gt;00111&lt;/td&gt;
      &lt;td&gt;7&lt;/td&gt;
      &lt;td&gt;Bell&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;ctrl&lt;/kbd&gt;+&lt;kbd&gt;h&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;1001000&lt;/td&gt;
      &lt;td&gt;72&lt;/td&gt;
      &lt;td&gt;H&lt;/td&gt;
      &lt;td&gt;01000&lt;/td&gt;
      &lt;td&gt;8&lt;/td&gt;
      &lt;td&gt;Backspace&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;ctrl&lt;/kbd&gt;+&lt;kbd&gt;i&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;1001001&lt;/td&gt;
      &lt;td&gt;73&lt;/td&gt;
      &lt;td&gt;I&lt;/td&gt;
      &lt;td&gt;01001&lt;/td&gt;
      &lt;td&gt;9&lt;/td&gt;
      &lt;td&gt;Horizontal Tab&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;ctrl&lt;/kbd&gt;+&lt;kbd&gt;j&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;1001010&lt;/td&gt;
      &lt;td&gt;74&lt;/td&gt;
      &lt;td&gt;I&lt;/td&gt;
      &lt;td&gt;01010&lt;/td&gt;
      &lt;td&gt;10&lt;/td&gt;
      &lt;td&gt;Line Feed&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;ctrl&lt;/kbd&gt;+&lt;kbd&gt;m&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;1001101&lt;/td&gt;
      &lt;td&gt;77&lt;/td&gt;
      &lt;td&gt;M&lt;/td&gt;
      &lt;td&gt;01101&lt;/td&gt;
      &lt;td&gt;13&lt;/td&gt;
      &lt;td&gt;Carriage Return&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;ctrl&lt;/kbd&gt;+&lt;kbd&gt;[&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;1011011&lt;/td&gt;
      &lt;td&gt;91&lt;/td&gt;
      &lt;td&gt;[&lt;/td&gt;
      &lt;td&gt;11011&lt;/td&gt;
      &lt;td&gt;27&lt;/td&gt;
      &lt;td&gt;Escape&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;
  This explains why typing &lt;kbd&gt;ctrl&lt;/kbd&gt;+&lt;kbd&gt;g&lt;/kbd&gt; in a modern
  terminal emulator produces an audible beep or a visual flash,
  why &lt;kbd&gt;ctrl&lt;/kbd&gt;+&lt;kbd&gt;h&lt;/kbd&gt; erases a character and so on.  This
  also explains why we can type &lt;kbd&gt;ctrl&lt;/kbd&gt;+&lt;kbd&gt;[&lt;/kbd&gt; in Vim to
  escape from insert mode to normal mode.  While we can
  type &lt;em&gt;escape&lt;/em&gt; with the &lt;kbd&gt;esc&lt;/kbd&gt; key on the keyboard, we
  can do so with the &lt;kbd&gt;ctrl&lt;/kbd&gt;+&lt;kbd&gt;[&lt;/kbd&gt; key too within the
  terminal.
&lt;/p&gt;
&lt;p&gt;
  The keen eyed may notice that the table above has lowercase letters
  in the first column but the second and third columns use the code of
  the corresponding uppercase letters.  The lowercase letters in the
  first column is merely a notation I am using in this post to
  identify the keys on a keyboard.  They don&apos;t actually mean lowercase
  characters.  In fact, the very early keyboards only had uppercase
  letters and they simply toggled the 7th least significant bit of the
  modified character to obtain the control code.
&lt;/p&gt;
&lt;p&gt;
  By the way, an interesting thing worth noting here is that even if
  we do consider the code of the lowercase character and pick only its
  five least significant bits, we get the same control code as we
  would get if we started with the corresponding uppercase character.
  For example, consider the key sequence
  &lt;kbd&gt;ctrl&lt;/kbd&gt;+&lt;kbd&gt;g&lt;/kbd&gt;.  The uppercase character &lt;code&gt;G&lt;/code&gt;
  has the code 71 (decimal 1000111) and the lowercase
  character &lt;code&gt;g&lt;/code&gt; has the code 103 (decimal 1100111).  The
  five least significant bits are equal in both.  So when we pick the
  five least significant bits and discard the rest, we get the same
  result, i.e. 7 (binary 111) which is the code of the &lt;em&gt;bell&lt;/em&gt;
  character.  This is due to the fact that the five least significant
  bits of the code of a lowercase character is exactly the same as
  that of the corresponding uppercase character.  They differ only in
  their sixth least significant bit.  This is only an interesting
  observation.  It is of little significance though because like I
  mentioned earlier, the early keyboards only flipped a bit in the
  code of the uppercase characters when the &lt;kbd&gt;ctrl&lt;/kbd&gt; modifier
  was applied.
&lt;/p&gt;
&lt;p&gt;
  In addition to what we have discussed so far, some terminal
  emulators also implement a few special rules such as the following:
&lt;/p&gt;
&lt;table class=&quot;grid mono&quot;&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th rowspan=&quot;2&quot;&gt;Key&lt;/th&gt;
      &lt;th colspan=&quot;3&quot;&gt;Modified Character&lt;/th&gt;
      &lt;th colspan=&quot;3&quot;&gt;Resulting Character&lt;/th&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;Binary&lt;/th&gt;
      &lt;th&gt;Decimal&lt;/th&gt;
      &lt;th&gt;Character&lt;/th&gt;
      &lt;th&gt;Binary&lt;/th&gt;
      &lt;th&gt;Decimal&lt;/th&gt;
      &lt;th&gt;Character&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody style=&quot;font-family: monospace, monospace&quot;&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;ctrl&lt;/kbd&gt;+&lt;kbd&gt;space&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;0100000&lt;/td&gt;
      &lt;td&gt;32&lt;/td&gt;
      &lt;td&gt;Space&lt;/td&gt;
      &lt;td&gt;0&lt;/td&gt;
      &lt;td&gt;0&lt;/td&gt;
      &lt;td&gt;Null&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;ctrl&lt;/kbd&gt;+&lt;kbd&gt;?&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;0111111&lt;/td&gt;
      &lt;td&gt;63&lt;/td&gt;
      &lt;td&gt;?&lt;/td&gt;
      &lt;td&gt;1111111&lt;/td&gt;
      &lt;td&gt;127&lt;/td&gt;
      &lt;td&gt;Delete&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;
  One could argue that the first row shows a straightforward example
  of picking the least significiant five bits to arrive at the control
  code, so it is not really a special case.  That is a fair point.
  However, in the history of computing, different systems have
  implemented slightly different methods to compute the resulting
  control codes from our input.  Flipping the 7th least significant
  bit was one of the early methods.  Turning off only the the 6th and
  the 7th least significant bits has been another method.  Subtracting
  64 from the character code has been yet another one.  These
  different methods produce identical results for the first table but
  not so for the second table.  For example, while turning off the 6th
  and 7th least significnat bits of 32 (the code of the &lt;em&gt;space&lt;/em&gt;
  character) does give us 0 but merely flipping its 7th bit does not.
  Further, note that allowing &lt;kbd&gt;ctrl&lt;/kbd&gt;+&lt;kbd&gt;space&lt;/kbd&gt; to
  produce the null character is a bit redundant
  because &lt;kbd&gt;ctrl&lt;/kbd&gt;+&lt;kbd&gt;@&lt;/kbd&gt; already did that right from the
  days of very early keyboards.  The second entry above is also a
  special rule because we neither turn off bits nor subtract 64.
  Instead, we flip the 7th least significant bit which amounts to
  adding 64 to the code of the modified character.  It is also the
  only control code that has its 6th and 7th least significant bits
  turned on.
&lt;/p&gt;
&lt;h2 id=&quot;meta-key-sequences&quot;&gt;Meta Key Sequences&lt;/h2&gt;
&lt;p&gt;
  The &lt;kbd&gt;meta&lt;/kbd&gt; key no longer exists on modern keyboards.  On
  modern keyboards, we use the &lt;kbd&gt;alt&lt;/kbd&gt; or &lt;kbd&gt;option&lt;/kbd&gt; key
  instead of &lt;kbd&gt;meta&lt;/kbd&gt;.  For example, when a shell&apos;s manual says
  that we need to type &lt;kbd&gt;meta&lt;/kbd&gt;+&lt;kbd&gt;b&lt;/kbd&gt; to move the cursor
  back by one word, what we really type on a modern keyboard is
  either &lt;kbd&gt;alt&lt;/kbd&gt;+&lt;kbd&gt;b&lt;/kbd&gt;
  or &lt;kbd&gt;option&lt;/kbd&gt;+&lt;kbd&gt;b&lt;/kbd&gt;.  In fact, the &lt;code&gt;cat&lt;/code&gt;
  and &lt;code&gt;od&lt;/code&gt; experiments mentioned earlier show that when we
  type the modern alternative for the &lt;kbd&gt;meta&lt;/kbd&gt; key along with
  another key, what most terminals really send to the underlying
  program is an &lt;em&gt;escape&lt;/em&gt; control code (27) followed by the code
  of the modified character.
&lt;/p&gt;
&lt;table class=&quot;grid mono&quot;&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Meta Key Sequence&lt;/th&gt;
      &lt;th&gt;Escape Key Sequence&lt;/th&gt;
      &lt;th&gt;Control Key Sequence&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;meta&lt;/kbd&gt;+&lt;kbd&gt;b&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;&lt;kbd&gt;esc&lt;/kbd&gt; &lt;kbd&gt;b&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;&lt;kbd&gt;ctrl&lt;/kbd&gt;+&lt;kbd&gt;[&lt;/kbd&gt; &lt;kbd&gt;b&lt;/kbd&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;meta&lt;/kbd&gt;+&lt;kbd&gt;f&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;&lt;kbd&gt;esc&lt;/kbd&gt; &lt;kbd&gt;f&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;&lt;kbd&gt;ctrl&lt;/kbd&gt;+&lt;kbd&gt;[&lt;/kbd&gt; &lt;kbd&gt;f&lt;/kbd&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;meta&lt;/kbd&gt;+&lt;kbd&gt;/&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;&lt;kbd&gt;esc&lt;/kbd&gt; &lt;kbd&gt;/&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;&lt;kbd&gt;ctrl&lt;/kbd&gt;+&lt;kbd&gt;[&lt;/kbd&gt; &lt;kbd&gt;/&lt;/kbd&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;meta&lt;/kbd&gt;+&lt;kbd&gt;:&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;&lt;kbd&gt;esc&lt;/kbd&gt; &lt;kbd&gt;:&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;&lt;kbd&gt;ctrl&lt;/kbd&gt;+&lt;kbd&gt;[&lt;/kbd&gt; &lt;kbd&gt;:&lt;/kbd&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;
  There are several layers of software involved between the keyboard
  input and the application running in the terminal and the exact
  behaviour of the &lt;kbd&gt;alt&lt;/kbd&gt; or &lt;kbd&gt;option&lt;/kbd&gt; key may vary
  depending on the configuration of each of these layers.  Terminal
  configuration alone is a complex topic that can be discussed
  extensively.  However, the behaviour described here is one of the
  popular defaults.  Alternative behaviours exist but they generally
  produce similar effects for the user.
&lt;/p&gt;
&lt;h2 id=&quot;awkward-vim-tricks&quot;&gt;Awkward Vim Tricks&lt;/h2&gt;
&lt;p&gt;
  Most Vim users know that we can go from insert mode to command-line
  mode and search for patterns by typing
  either &lt;kbd&gt;esc&lt;/kbd&gt; &lt;kbd&gt;/&lt;/kbd&gt; or &lt;kbd&gt;C-[&lt;/kbd&gt; &lt;kbd&gt;/&lt;/kbd&gt;.
  But what some people may find surprising is that we can also go from
  insert mode to searching patterns simply by typing
  &lt;kbd&gt;meta&lt;/kbd&gt;+&lt;kbd&gt;/&lt;/kbd&gt;.  Yes, this can be verified by running
  Vim in a terminal emulator.  While insert mode is active,
  type &lt;kbd&gt;alt&lt;/kbd&gt;+&lt;kbd&gt;/&lt;/kbd&gt; or &lt;kbd&gt;option&lt;/kbd&gt;+&lt;kbd&gt;/&lt;/kbd&gt;
  and the current mode should instantly switch to the command-line
  mode with the forward-slash (&lt;samp&gt;/&lt;/samp&gt;) prompt waiting for our
  search pattern.  This works only in a terminal emulator.  It may not
  work in the graphical version of Vim.  The table above illustrates
  why this works in a terminal emulator.
&lt;/p&gt;
&lt;p&gt;
  Similarly, in a Vim instance running within a terminal emulator, we
  can type &lt;kbd&gt;meta&lt;/kbd&gt;+&lt;kbd&gt;:&lt;/kbd&gt; to go directly from insert
  mode to command-line mode and enter Ex commands.  We can
  type &lt;kbd&gt;meta&lt;/kbd&gt;+&lt;kbd&gt;0&lt;/kbd&gt; to go directly from insert mode to
  the first character of a line or type &lt;kbd&gt;meta&lt;/kbd&gt;+&lt;kbd&gt;$&lt;/kbd&gt;
  to go to the end of the line and so on.  These are equivalent to
  typing &lt;kbd&gt;esc&lt;/kbd&gt; &lt;kbd&gt;0&lt;/kbd&gt;, &lt;kbd&gt;esc&lt;/kbd&gt; &lt;kbd&gt;$&lt;/kbd&gt;,
  etc.
&lt;/p&gt;
&lt;p&gt;
  More interestingly, we can type &lt;kbd&gt;meta&lt;/kbd&gt;+&lt;kbd&gt;O&lt;/kbd&gt; to open
  a line above, &lt;kbd&gt;meta&lt;/kbd&gt;+&lt;kbd&gt;A&lt;/kbd&gt; to append text at the end
  of the line, &lt;kbd&gt;meta&lt;/kbd&gt;+&lt;kbd&gt;I&lt;/kbd&gt; to append text at the
  beginning of the line or &lt;kbd&gt;meta&lt;/kbd&gt;+&lt;kbd&gt;S&lt;/kbd&gt; to delete the
  current line while staying in insert mode!  Since the Vim
  commands &lt;kbd&gt;O&lt;/kbd&gt;, &lt;kbd&gt;A&lt;/kbd&gt;, &lt;kbd&gt;I&lt;/kbd&gt; and &lt;kbd&gt;S&lt;/kbd&gt;
  leave us back in insert mode, we are able to perform an editing
  operation that involves leaving the insert mode, doing something
  interesting and returning to insert mode instantly using the
  the &lt;kbd&gt;meta&lt;/kbd&gt; key combination.  The following table summarises
  these observations:
&lt;/p&gt;
&lt;table class=&quot;grid mono&quot;&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Initial Mode&lt;/th&gt;
      &lt;th&gt;Meta Key Sequence&lt;/th&gt;
      &lt;th&gt;Equivalent To&lt;/th&gt;
      &lt;th&gt;Operation&lt;/th&gt;
      &lt;th&gt;Final State&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Insert&lt;/td&gt;
      &lt;td&gt;&lt;kbd&gt;meta&lt;/kbd&gt;+&lt;kbd&gt;/&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;&lt;kbd&gt;esc&lt;/kbd&gt; &lt;kbd&gt;/&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;Enter command-line mode to search a pattern&lt;/td&gt;
      &lt;td&gt;Command-line&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Insert&lt;/td&gt;
      &lt;td&gt;&lt;kbd&gt;meta&lt;/kbd&gt;+&lt;kbd&gt;:&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;&lt;kbd&gt;esc&lt;/kbd&gt; &lt;kbd&gt;:&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;Enter command-line mode to enter Ex command&lt;/td&gt;
      &lt;td&gt;Command-line&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Insert&lt;/td&gt;
      &lt;td&gt;&lt;kbd&gt;meta&lt;/kbd&gt;+&lt;kbd&gt;0&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;&lt;kbd&gt;esc&lt;/kbd&gt; &lt;kbd&gt;0&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;Move to the first character of the line&lt;/td&gt;
      &lt;td&gt;Normal&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Insert&lt;/td&gt;
      &lt;td&gt;&lt;kbd&gt;meta&lt;/kbd&gt;+&lt;kbd&gt;$&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;&lt;kbd&gt;esc&lt;/kbd&gt; &lt;kbd&gt;$&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;Move to the end of the line&lt;/td&gt;
      &lt;td&gt;Normal&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Insert&lt;/td&gt;
      &lt;td&gt;&lt;kbd&gt;meta&lt;/kbd&gt;+&lt;kbd&gt;O&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;&lt;kbd&gt;esc&lt;/kbd&gt; &lt;kbd&gt;O&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;Begin a new line above and insert text&lt;/td&gt;
      &lt;td&gt;Insert&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Insert&lt;/td&gt;
      &lt;td&gt;&lt;kbd&gt;meta&lt;/kbd&gt;+&lt;kbd&gt;A&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;&lt;kbd&gt;esc&lt;/kbd&gt; &lt;kbd&gt;A&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;Append text to the end of line&lt;/td&gt;
      &lt;td&gt;Insert&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Insert&lt;/td&gt;
      &lt;td&gt;&lt;kbd&gt;meta&lt;/kbd&gt;+&lt;kbd&gt;I&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;&lt;kbd&gt;esc&lt;/kbd&gt; &lt;kbd&gt;I&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;Insert text before the first non-blank in line&lt;/td&gt;
      &lt;td&gt;Insert&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Insert&lt;/td&gt;
      &lt;td&gt;&lt;kbd&gt;meta&lt;/kbd&gt;+&lt;kbd&gt;S&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;&lt;kbd&gt;esc&lt;/kbd&gt; &lt;kbd&gt;S&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;Delete line and insert text&lt;/td&gt;
      &lt;td&gt;Insert&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;
  There is no good reason to use Vim like this but it works, thanks to
  the quirky history of Unix terminals and keyboards!
&lt;/p&gt;
<!-- ### -->
&lt;p&gt;
  &lt;a href="https://susam.net/control-escape-meta-tricks.html"&gt;Read on website&lt;/a&gt; |
  &lt;a href=&quot;https://susam.net/tag/unix.html&quot;&gt;#unix&lt;/a&gt; |
  &lt;a href=&quot;https://susam.net/tag/shell.html&quot;&gt;#shell&lt;/a&gt; |
  &lt;a href=&quot;https://susam.net/tag/technology.html&quot;&gt;#technology&lt;/a&gt;
&lt;/p&gt;
<!-- END HTML -->
    </content>
  </entry>
  <entry>
    <title>From XON/XOFF to Forward Incremental Search</title>
    <link href="https://susam.net/from-xon-xoff-to-forward-incremental-search.html"/>
    <id>urn:uuid:b8e4d86c-6221-49bd-b600-3dd723f319e0</id>
    <updated>2022-08-13T00:00:00Z</updated>
    <content type="html">
<!-- BEGIN HTML -->
&lt;h2 id=&quot;xon-xoff&quot;&gt;XON/XOFF&lt;/h2&gt;
&lt;p&gt;
  In the olden days of computing, software flow control with control
  codes XON and XOFF was a necessary feature that dumb terminals
  needed to support.  When a terminal received more data than it could
  display, there needed to be a way for the terminal to tell the
  remote host to pause sending more data.  The control code 19 was
  chosen for this.  The control code 17 was chosen to tell the remote
  host to resume transmission of data.
&lt;/p&gt;
&lt;p&gt;
  The control code 19 is called Device Control 3 (DC3) in the ASCII
  chart.  It is also known as &quot;transmit off&quot; (XOFF).  The control code
  17 is called Device Control 1 (DC1) as well as &quot;transmit on&quot; (XON).
  Now how does a user of the terminal really send these control codes?
  Well, how do they send any control code?  Using the &lt;kbd&gt;ctrl&lt;/kbd&gt;
  key of course.
&lt;/p&gt;
&lt;p&gt;
  Let us take a step back and see how a user can send familiar control
  codes on modern terminal emulators, like say, the terminal software
  we find on a Unix or Linux desktop environment.  While any sane
  computer user would just type the &lt;kbd&gt;tab&lt;/kbd&gt; key to insert a tab
  character, one could also type &lt;kbd&gt;ctrl&lt;/kbd&gt;+&lt;kbd&gt;i&lt;/kbd&gt; to
  insert a tab character.  The character &lt;code&gt;I&lt;/code&gt; has code 73
  (binary 1001001) and holding the &lt;kbd&gt;ctrl&lt;/kbd&gt; key while typing it
  results in a control code made by taking 73 (binary 1001001),
  keeping its five least significant bits and discarding the rest to
  get the control code 9 (binary 1001) which is the code of the tab
  character.  In other words, we get the control code by performing a
  bitwise AND operation on the code of the character being modified
  with binary code of 31 (binary 0011111).
&lt;/p&gt;
&lt;p&gt;
  In case you are wondering, if we get the same result if we choose
  the binary code of the lowercase &lt;code&gt;i&lt;/code&gt; to perform the
  aforementioned operation, the answer is, yes.  While the code of
  uppercase &lt;code&gt;I&lt;/code&gt; is 73 (binary 1001001), that of
  lowercase &lt;code&gt;i&lt;/code&gt; is 105 (binary 1101001).  The right-most
  five bits are same for both.  Thus when we preserve the five least
  significant bits and discard the rest, we get the control code 9
  (binary 1001) in both cases.  This is a neat result due to the fact
  that the five least significant bits of the code of a lowercase
  character is exactly the same as that of the corresponding uppercase
  character.  They differ only in their sixth least significant bit.
  That bit is on for the lowercase character but off for the
  corresponding uppercase character.  This is just an interesting
  observation as far as this post is concerned.  The very early
  keyboards did not have lowercase letters.  They only had uppercase
  letters and when the &lt;kbd&gt;ctrl&lt;/kbd&gt; key is pressed together with a
  letter on such keyboards, the 7th bit of the character code was
  flipped to get the control code.
&lt;/p&gt;
&lt;p&gt;
  The bitwise operation mentioned earlier explains why
  typing &lt;kbd&gt;ctrl&lt;/kbd&gt;+&lt;kbd&gt;h&lt;/kbd&gt; sends a backspace,
  typing &lt;kbd&gt;ctrl&lt;/kbd&gt;+&lt;kbd&gt;j&lt;/kbd&gt; sends a newline and
  typing &lt;kbd&gt;ctrl&lt;/kbd&gt;+&lt;kbd&gt;g&lt;/kbd&gt; plays a bell.  In modern
  terminal emulators these days, the bell often manifests in the form
  of an audible beep or a visual flash.  Here is a table that
  summarises these control codes and a few more:
&lt;/p&gt;
&lt;table class=&quot;grid mono&quot;&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th rowspan=&quot;2&quot;&gt;Key&lt;/th&gt;
      &lt;th colspan=&quot;3&quot;&gt;Modified Character&lt;/th&gt;
      &lt;th colspan=&quot;3&quot;&gt;Control Character&lt;/th&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;Binary&lt;/th&gt;
      &lt;th&gt;Decimal&lt;/th&gt;
      &lt;th&gt;Character&lt;/th&gt;
      &lt;th&gt;Binary&lt;/th&gt;
      &lt;th&gt;Decimal&lt;/th&gt;
      &lt;th&gt;Character&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;ctrl&lt;/kbd&gt;+&lt;kbd&gt;@&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;1000000&lt;/td&gt;
      &lt;td&gt;64&lt;/td&gt;
      &lt;td&gt;@&lt;/td&gt;
      &lt;td&gt;00000&lt;/td&gt;
      &lt;td&gt;0&lt;/td&gt;
      &lt;td&gt;Null&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;ctrl&lt;/kbd&gt;+&lt;kbd&gt;g&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;1000111&lt;/td&gt;
      &lt;td&gt;71&lt;/td&gt;
      &lt;td&gt;G&lt;/td&gt;
      &lt;td&gt;00111&lt;/td&gt;
      &lt;td&gt;7&lt;/td&gt;
      &lt;td&gt;Bell&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;ctrl&lt;/kbd&gt;+&lt;kbd&gt;h&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;1001000&lt;/td&gt;
      &lt;td&gt;72&lt;/td&gt;
      &lt;td&gt;H&lt;/td&gt;
      &lt;td&gt;01000&lt;/td&gt;
      &lt;td&gt;8&lt;/td&gt;
      &lt;td&gt;Backspace&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;ctrl&lt;/kbd&gt;+&lt;kbd&gt;i&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;1001001&lt;/td&gt;
      &lt;td&gt;73&lt;/td&gt;
      &lt;td&gt;I&lt;/td&gt;
      &lt;td&gt;01001&lt;/td&gt;
      &lt;td&gt;9&lt;/td&gt;
      &lt;td&gt;Horizontal Tab&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;ctrl&lt;/kbd&gt;+&lt;kbd&gt;j&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;1001010&lt;/td&gt;
      &lt;td&gt;74&lt;/td&gt;
      &lt;td&gt;I&lt;/td&gt;
      &lt;td&gt;01010&lt;/td&gt;
      &lt;td&gt;10&lt;/td&gt;
      &lt;td&gt;Line Feed&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;ctrl&lt;/kbd&gt;+&lt;kbd&gt;m&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;1001101&lt;/td&gt;
      &lt;td&gt;77&lt;/td&gt;
      &lt;td&gt;M&lt;/td&gt;
      &lt;td&gt;01101&lt;/td&gt;
      &lt;td&gt;13&lt;/td&gt;
      &lt;td&gt;Carriage Return&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;ctrl&lt;/kbd&gt;+&lt;kbd&gt;[&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;1011011&lt;/td&gt;
      &lt;td&gt;91&lt;/td&gt;
      &lt;td&gt;[&lt;/td&gt;
      &lt;td&gt;11011&lt;/td&gt;
      &lt;td&gt;27&lt;/td&gt;
      &lt;td&gt;Escape&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;
  The last row in the table above explains why we can also
  type &lt;kbd&gt;ctrl&lt;/kbd&gt;+&lt;kbd&gt;[&lt;/kbd&gt; in Vim to escape from insert mode
  to normal mode.  This is, in fact, one of the convenient ways for
  touch-typists to return to normal mode in Vim instead of clumsily
  stretching the left hand fingers out to reach the &lt;kbd&gt;esc&lt;/kbd&gt; key
  which is usually poorly located at the corner of most keyboards.
&lt;/p&gt;
&lt;p&gt;
  There is a bit of oversimplication in the description above.
  Throughout the history of computing, different systems have used
  slightly different methods to compute the resulting control code
  when the &lt;kbd&gt;ctrl&lt;/kbd&gt; modifier key is held.  Toggling the 7th
  least significant bit was an early method.  Turning off both the 6th
  and 7th least significant bits is another method.  Subtracting 64
  from the character code is yet another method.  These are
  implementation details and these various implementation methods lead
  to the same results for the examples in the table above.  Then there
  are some special rules too.  For example, many terminals implement a
  special rule to make &lt;kbd&gt;ctrl&lt;/kbd&gt;+&lt;kbd&gt;space&lt;/kbd&gt; behave the
  same as &lt;kbd&gt;ctrl&lt;/kbd&gt;+&lt;kbd&gt;@&lt;/kbd&gt; thus producing the null
  character.  Further &lt;kbd&gt;ctrl&lt;/kbd&gt;+&lt;kbd&gt;?&lt;/kbd&gt; produces the delete
  character in some terminals.  These special rules are summarised in
  the table below.
&lt;/p&gt;
&lt;table class=&quot;grid mono&quot;&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th rowspan=&quot;2&quot;&gt;Key&lt;/th&gt;
      &lt;th colspan=&quot;3&quot;&gt;Modified Character&lt;/th&gt;
      &lt;th colspan=&quot;3&quot;&gt;Resulting Character&lt;/th&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;Binary&lt;/th&gt;
      &lt;th&gt;Decimal&lt;/th&gt;
      &lt;th&gt;Character&lt;/th&gt;
      &lt;th&gt;Binary&lt;/th&gt;
      &lt;th&gt;Decimal&lt;/th&gt;
      &lt;th&gt;Character&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;ctrl&lt;/kbd&gt;+&lt;kbd&gt;space&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;0100000&lt;/td&gt;
      &lt;td&gt;32&lt;/td&gt;
      &lt;td&gt;Space&lt;/td&gt;
      &lt;td&gt;0&lt;/td&gt;
      &lt;td&gt;0&lt;/td&gt;
      &lt;td&gt;Null&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;ctrl&lt;/kbd&gt;+&lt;kbd&gt;?&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;0111111&lt;/td&gt;
      &lt;td&gt;63&lt;/td&gt;
      &lt;td&gt;?&lt;/td&gt;
      &lt;td&gt;1111111&lt;/td&gt;
      &lt;td&gt;127&lt;/td&gt;
      &lt;td&gt;Delete&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;
  For the purpose of this blog post, we don&apos;t need to worry about
  these special rules.  Let us get back to the control codes 19 and 17
  that represent XOFF and XON.  Here is how the table looks for them:
&lt;/p&gt;
&lt;table class=&quot;grid mono&quot;&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th rowspan=&quot;2&quot;&gt;Key&lt;/th&gt;
      &lt;th colspan=&quot;3&quot;&gt;Modified Character&lt;/th&gt;
      &lt;th colspan=&quot;3&quot;&gt;Resulting Character&lt;/th&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;Binary&lt;/th&gt;
      &lt;th&gt;Decimal&lt;/th&gt;
      &lt;th&gt;Character&lt;/th&gt;
      &lt;th&gt;Binary&lt;/th&gt;
      &lt;th&gt;Decimal&lt;/th&gt;
      &lt;th&gt;Character&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;ctrl&lt;/kbd&gt;+&lt;kbd&gt;q&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;1010001&lt;/td&gt;
      &lt;td&gt;81&lt;/td&gt;
      &lt;td&gt;Q&lt;/td&gt;
      &lt;td&gt;10001&lt;/td&gt;
      &lt;td&gt;17&lt;/td&gt;
      &lt;td&gt;DC1 (XON)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;kbd&gt;ctrl&lt;/kbd&gt;+&lt;kbd&gt;s&lt;/kbd&gt;&lt;/td&gt;
      &lt;td&gt;1010011&lt;/td&gt;
      &lt;td&gt;83&lt;/td&gt;
      &lt;td&gt;S&lt;/td&gt;
      &lt;td&gt;10011&lt;/td&gt;
      &lt;td&gt;19&lt;/td&gt;
      &lt;td&gt;DC3 (XOFF)&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;
  We see that a user can type &lt;kbd&gt;ctrl&lt;/kbd&gt;+&lt;kbd&gt;s&lt;/kbd&gt; to send the
  control code XOFF and then &lt;kbd&gt;ctrl&lt;/kbd&gt;+&lt;kbd&gt;q&lt;/kbd&gt; to send the
  control code XON.  Although we do not use dumb terminals anymore,
  these conventions have survived in various forms in our modern
  terminal emulators.  To see a glimpse of it, launch the terminal
  that comes with a modern operating system, then run &lt;code&gt;ping
  localhost&lt;/code&gt; and while this command is printing its output,
  type &lt;kbd&gt;ctrl&lt;/kbd&gt;+&lt;kbd&gt;s&lt;/kbd&gt;.  The terminal should pause
  printing the output of the command.  Then
  type &lt;kbd&gt;ctrl&lt;/kbd&gt;+&lt;kbd&gt;q&lt;/kbd&gt; and the terminal should resume
  printing the output.
&lt;/p&gt;
&lt;h2 id=&quot;incremental-search-in-bash-zsh&quot;&gt;Incremental Search in Bash/Zsh&lt;/h2&gt;
&lt;p&gt;
  Let us now take a look at the shells that run within the terminals.
  Both Bash and Zsh are very popular these days.  Both these shells
  have excellent support for performing incremental searches through
  the input history.  To see a quick demonstration of this, open a new
  terminal that runs either Bash or Zsh and run these commands:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;echo foo
echo bar
cal
uname
echo baz&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
  Now type &lt;kbd&gt;ctrl&lt;/kbd&gt;+&lt;kbd&gt;r&lt;/kbd&gt; followed by &lt;code&gt;echo&lt;/code&gt;.
  This should invoke the reverse search feature of the shell and
  automatically complete the partial command &lt;code&gt;echo&lt;/code&gt;
  to &lt;code&gt;echo baz&lt;/code&gt;.  Type &lt;kbd&gt;ctrl&lt;/kbd&gt;+&lt;kbd&gt;r&lt;/kbd&gt; again
  to move back in the input history and autocomplete the command
  to &lt;code&gt;echo bar&lt;/code&gt;.  We can type &lt;kbd&gt;enter&lt;/kbd&gt; anytime we
  use the reverse search feature to execute the automatically
  completed command.  Typing &lt;kbd&gt;ctrl&lt;/kbd&gt;+&lt;kbd&gt;r&lt;/kbd&gt; yet another
  time should bring the &lt;code&gt;echo foo&lt;/code&gt; command at the shell
  prompt.
&lt;/p&gt;
&lt;p&gt;
  What if we went too far back in the input history and now want to go
  forward?  There is a good news and there is some bad news.  The good
  news is that both Bash and Zsh support forward search using
  the &lt;kbd&gt;ctrl&lt;/kbd&gt;+&lt;kbd&gt;s&lt;/kbd&gt; key sequence.  The bad news is that
  this key sequence may not reach the shell.  Most terminal emulators
  consume this key sequence and interpret it as the control code XOFF.
&lt;/p&gt;

&lt;h2 id=&quot;conflict&quot;&gt;The Conflict&lt;/h2&gt;
&lt;p&gt;
  In the previous two sections, we have seen that the
  &lt;kbd&gt;ctrl&lt;/kbd&gt;+&lt;kbd&gt;s&lt;/kbd&gt; key sequence is used to send the
  control code XOFF.  But the same key sequence is also used for
  forward incremental search in Bash and Zsh.  Since the terminal
  consumes this key sequence and interprets it as the control code
  XOFF, the shell never sees the key sequence.  As a result, the
  forward incremental search functionality does not work when we type
  this key sequence in the shell.
&lt;/p&gt;
&lt;p&gt;
  Bash offers the incremental search facility via a wonderful piece of
  library known as the the GNU Readline Library.  ZSH offers this
  facility with its own Zsh Line Editor (ZLE).  So other tools that
  rely on these libraries to offer line editing and history capability
  are also affected by this conflict.  For example, many builds of
  Python offer line editing and history capability using GNU Readline,
  so while &lt;kbd&gt;ctrl&lt;/kbd&gt;+&lt;kbd&gt;r&lt;/kbd&gt; works fine to perform reverse
  search in the Python interpreter, it is very likely
  that &lt;kbd&gt;ctrl&lt;/kbd&gt;+&lt;kbd&gt;s&lt;/kbd&gt; does not work to perform forward
  search.
&lt;/p&gt;
&lt;h2 id=&quot;reclaim-forward-incremental-search&quot;&gt;Reclaim Forward Incremental Search&lt;/h2&gt;
&lt;p&gt;
  We can forfeit the usage of control codes XON/XOFF to reclaim
  forward incremental search.  Here is the command to disable XON/XOFF
  output control in the terminal:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;stty -ixon&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
  After running the command, &lt;kbd&gt;ctrl&lt;/kbd&gt;+&lt;kbd&gt;s&lt;/kbd&gt; is no longer
  consumed by the terminal to pause the output.  To confirm that
  forward incremental search works now, first run the above command
  and then run the following commands:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;echo foo
echo bar
cal
uname
echo baz&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
  Now type &lt;kbd&gt;ctrl&lt;/kbd&gt;+&lt;kbd&gt;r&lt;/kbd&gt; followed by &lt;code&gt;echo&lt;/code&gt;
  and the input line should be automatically completed to &lt;code&gt;echo
  baz&lt;/code&gt;.  Type &lt;kbd&gt;ctrl&lt;/kbd&gt;+&lt;kbd&gt;r&lt;/kbd&gt; again and &lt;code&gt;echo
  bar&lt;/code&gt; should appear at the shell prompt.
  Type &lt;kbd&gt;ctrl&lt;/kbd&gt;+&lt;kbd&gt;r&lt;/kbd&gt; one more time to bring the
  command &lt;code&gt;echo foo&lt;/code&gt; at the shell prompt.
&lt;/p&gt;
&lt;p&gt;
  Now type &lt;kbd&gt;ctrl&lt;/kbd&gt;+&lt;kbd&gt;s&lt;/kbd&gt; once and the search facility
  should switch itself to forward incremental search.  The search
  prompt should change to show this.  For example, in Bash the search
  prompt changes from &lt;code&gt;reverse-i-search:&lt;/code&gt;
  to &lt;code&gt;i-search:&lt;/code&gt; to indicate this.  In Zsh, the search
  prompt changes from &lt;code&gt;bck-i-search:&lt;/code&gt;
  to &lt;code&gt;fwd-i-search:&lt;/code&gt;.
&lt;/p&gt;
&lt;p&gt;
  Now type &lt;kbd&gt;ctrl&lt;/kbd&gt;+&lt;kbd&gt;s&lt;/kbd&gt; again and the input line
  should be automatically completed to &lt;code&gt;echo bar&lt;/code&gt;.
  Type &lt;kbd&gt;ctrl&lt;/kbd&gt;+&lt;kbd&gt;s&lt;/kbd&gt; again to bring back &lt;code&gt;echo
  baz&lt;/code&gt; at the shell prompt.  This is the forward incremental
  search in action.
&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;
  I believe the forward incremental search facility offered in shells
  and other tools with line editing and history capabilities is a very
  useful feature that can make navigating the input history very
  convenient.  However due to the default setting of most terminals,
  this rather splendid feature remains unusable.
&lt;/p&gt;
&lt;p&gt;
  I believe heavy terminal users should add the command &lt;code&gt;stty
  -ixon&lt;/code&gt; to their &lt;code&gt;~/.bash_profile&lt;/code&gt;
  or &lt;code&gt;~/.zshrc&lt;/code&gt;, so that the &lt;kbd&gt;ctrl&lt;/kbd&gt;+&lt;kbd&gt;s&lt;/kbd&gt;
  key sequence can be used for forward incremental search.  Forfeit
  XON/XOFF to reclaim forward incremental search!
&lt;/p&gt;
<!-- ### -->
&lt;p&gt;
  &lt;a href="https://susam.net/from-xon-xoff-to-forward-incremental-search.html"&gt;Read on website&lt;/a&gt; |
  &lt;a href=&quot;https://susam.net/tag/unix.html&quot;&gt;#unix&lt;/a&gt; |
  &lt;a href=&quot;https://susam.net/tag/shell.html&quot;&gt;#shell&lt;/a&gt; |
  &lt;a href=&quot;https://susam.net/tag/technology.html&quot;&gt;#technology&lt;/a&gt;
&lt;/p&gt;
<!-- END HTML -->
    </content>
  </entry>
  <entry>
    <title>Wordle With Grep</title>
    <link href="https://susam.net/wordle-with-grep.html"/>
    <id>urn:uuid:5e705240-72ed-4ef8-86a1-bf3a99f50d50</id>
    <updated>2022-01-22T00:00:00Z</updated>
    <content type="html">
<!-- BEGIN HTML -->
&lt;p&gt;
  Let us solve a couple of
  &lt;a href=&quot;https://www.powerlanguage.co.uk/wordle/&quot;&gt;Wordle&lt;/a&gt; games
  with the Unix &lt;code&gt;grep&lt;/code&gt; command and the
  Unix &lt;code&gt;words&lt;/code&gt; file.  The Wordle games #217, #218 and #219
  for 22&amp;nbsp;Jan&amp;nbsp;2022, 23&amp;nbsp;Jan&amp;nbsp;2022 and
  24&amp;nbsp;Jan&amp;nbsp;22 respectively are used as examples in this post.
  The output examples shown below are obtained using the words
  file &lt;code&gt;/usr/share/dict/words&lt;/code&gt;, GNU grep 3.6 and GNU bash
  5.1.4 on Debian GNU/Linux 11.2 (bullseye).
&lt;/p&gt;
&lt;p&gt;
  Note that the original Wordle game uses a different word list.
  Further, there are several Wordle clones which may have their own
  word lists.  For the purpose of this post, we will use the word list
  that comes with Debian.  We will solve each Wordle in a quick and
  dirty manner in this post.  The focus is going to be on making
  constant progress and reaching the solution quickly with simple
  shell commands.
&lt;/p&gt;
&lt;h2 id=&quot;contents&quot;&gt;Contents&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;#preliminary-work&quot;&gt;Preliminary Work&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#wordle-217&quot;&gt;Wordle #217&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#wordle-218&quot;&gt;Wordle #218&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#wordle-219&quot;&gt;Wordle #219&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;preliminary-work&quot;&gt;Preliminary Work&lt;/h2&gt;
&lt;p&gt;
  Before we start solving Wordle games, we will do some preliminary
  work.  We will create a convenient shell alias that automatically
  selects all five-letter words from the &lt;code&gt;words&lt;/code&gt; files.  We
  will also find a good word to enter as the first guess into the
  Wordle game.  The following steps elaborate this preliminary work:
&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;
      Make a shell alias named &lt;code&gt;words&lt;/code&gt; that selects all 5
      letter words from the words file.
    &lt;/p&gt;
&lt;pre&gt;&lt;samp&gt;$ &lt;kbd&gt;alias words=&apos;grep &quot;^[a-z]\{5\}$&quot; /usr/share/dict/words&apos;&lt;/kbd&gt;
$ &lt;kbd&gt;words | head -n 3&lt;/kbd&gt;
abaci
aback
abaft
$ &lt;kbd&gt;words | tail -n 3&lt;/kbd&gt;
zoned
zones
zooms
$ &lt;kbd&gt;words | wc -l&lt;/kbd&gt;
4594&lt;/samp&gt;&lt;/pre&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;
      For each letter in the English alphabet, count the number of
      five-letter words that contain the letter.  Rank each letter by
      this count.
    &lt;/p&gt;
&lt;pre&gt;&lt;samp&gt;$ &lt;kbd&gt;for c in {a..z}; do echo $(words | grep $c | wc -l) $c; done | sort -rn | head -n 15&lt;/kbd&gt;
2245 s
2149 e
1736 a
1404 r
1301 o
1231 i
1177 l
1171 t
975 n
924 d
810 u
757 c
708 p
633 h
623 y&lt;/samp&gt;&lt;/pre&gt;
    &lt;p&gt;
      The output shows that the letter &apos;s&apos; occurs in 2245 five-letter
      words, followed by &apos;e&apos; which occurs in 2149 five-letter words
      and so on.
    &lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;
      Find a word that contains the top five letters found in the
      previous step.
    &lt;/p&gt;
&lt;pre&gt;&lt;samp&gt;$ &lt;kbd&gt;words | grep s | grep e | grep a | grep r | grep o&lt;/kbd&gt;
arose&lt;/samp&gt;&lt;/pre&gt;
    &lt;p&gt;
      We will enter this word as the first guess in every Wordle game.
    &lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;
      In case, the word &quot;arose&quot; does not lead to any positive result,
      we will need another word to enter as our second guess.  Find a
      word that contains the next five top letters in the list found
      above.
    &lt;/p&gt;
&lt;pre&gt;&lt;samp&gt;$ &lt;kbd&gt;words | grep i | grep l | grep t | grep n | grep d&lt;/kbd&gt;
$ &lt;kbd&gt;words | grep i | grep l | grep t | grep n | grep u&lt;/kbd&gt;
until&lt;/samp&gt;&lt;/pre&gt;
    &lt;p&gt;
      We found that there is no such word that contains &apos;i&apos;, &apos;l&apos;, &apos;t&apos;,
      &apos;n&apos; and &apos;d&apos;.  So we got rid of &apos;d&apos; in our search and included
      &apos;u&apos; (the next highest ranking letter after &apos;d&apos;) instead to find
      the word &quot;until&quot;.  We will enter this word as the second guess
      if and only if the first guess (i.e. &quot;arose&quot;) does not lead to
      any positive result.
    &lt;/p&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;wordle-217&quot;&gt;Wordle #217&lt;/h2&gt;
&lt;p&gt;
  Let us now solve Wordle #217 for Sat,&amp;nbsp;22&amp;nbsp;Jan&amp;nbsp;2022
  with the following steps:
&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;
      Use the word &quot;arose&quot; as the first guess.  The following result
      appears:
    &lt;/p&gt;
    &lt;p style=&quot;font-family: monospace; font-weight: bold; color: #ddd&quot;&gt;
      &lt;span style=&quot;background: #333; padding: 0.5em&quot;&gt;A&lt;/span&gt;
      &lt;span style=&quot;background: #333; padding: 0.5em&quot;&gt;R&lt;/span&gt;
      &lt;span style=&quot;background: #333; padding: 0.5em&quot;&gt;O&lt;/span&gt;
      &lt;span style=&quot;background: #333; padding: 0.5em&quot;&gt;S&lt;/span&gt;
      &lt;span style=&quot;background: #585; padding: 0.5em&quot;&gt;E&lt;/span&gt;
    &lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;
      The previous result shows that the letter &apos;e&apos; occurs at the
      fifth place.  Further, the letters &apos;a&apos;, &apos;r&apos;, &apos;o&apos; and &apos;s&apos; do not
      occur anywhere in the word.  Look for words satisfying these
      constraints.
    &lt;/p&gt;
&lt;pre&gt;&lt;samp&gt;$ &lt;kbd&gt;words | grep &apos;....e&apos; | grep -v &apos;[aros]&apos; | head -n 5&lt;/kbd&gt;
beige
belie
belle
bible
bilge&lt;/samp&gt;&lt;/pre&gt;
    &lt;p&gt;
      Pick the word &quot;beige&quot; for the second guess and enter it into the
      Wordle game.  Note that since we are following a quick and dirty
      approach here, we do not spend any time figuring out which of
      the various five-letter words ending with the letter &apos;e&apos; is the
      most optimal choice for the next guess.  We simply pick the
      first word from the output above and enter it as the second
      guess.  The following result appears now:
    &lt;/p&gt;
    &lt;p style=&quot;font-family: monospace; font-weight: bold; color: #ddd&quot;&gt;
      &lt;span style=&quot;background: #333; padding: 0.5em&quot;&gt;B&lt;/span&gt;
      &lt;span style=&quot;background: #333; padding: 0.5em&quot;&gt;E&lt;/span&gt;
      &lt;span style=&quot;background: #b93; padding: 0.5em&quot;&gt;I&lt;/span&gt;
      &lt;span style=&quot;background: #333; padding: 0.5em&quot;&gt;G&lt;/span&gt;
      &lt;span style=&quot;background: #585; padding: 0.5em&quot;&gt;E&lt;/span&gt;
    &lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;
      The letter &apos;i&apos; occurs somewhere in the word but not at the third
      place.  Further the letters &apos;b&apos; and &apos;g&apos; do not occur anywhere in
      the word.  Also, the letter &apos;e&apos; does not occur anywhere apart
      from the fifth place.  The letter &apos;e&apos; in the gray tile in the
      second place confirms that the letter &apos;e&apos; does not repeat in the
      answer word.  Refine the previous command to add these
      constraints.
    &lt;/p&gt;
&lt;pre&gt;&lt;samp&gt;$ &lt;kbd&gt;words | grep &apos;[^e][^e][^ie][^e]e&apos; | grep i | grep -v &apos;[arosbg]&apos; | head -n 5&lt;/kbd&gt;
fiche
indue
lithe
mince
niche&lt;/samp&gt;&lt;/pre&gt;
    &lt;p&gt;
      Enter &quot;fiche&quot; as the third guess.  The following result appears:
    &lt;/p&gt;
    &lt;p style=&quot;font-family: monospace; font-weight: bold; color: #ddd&quot;&gt;
      &lt;span style=&quot;background: #333; padding: 0.5em&quot;&gt;F&lt;/span&gt;
      &lt;span style=&quot;background: #585; padding: 0.5em&quot;&gt;I&lt;/span&gt;
      &lt;span style=&quot;background: #b93; padding: 0.5em&quot;&gt;C&lt;/span&gt;
      &lt;span style=&quot;background: #333; padding: 0.5em&quot;&gt;H&lt;/span&gt;
      &lt;span style=&quot;background: #585; padding: 0.5em&quot;&gt;E&lt;/span&gt;
    &lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;
      The previous result shows that the letter &apos;i&apos; occurs at the
      second place.  Further, the letter &apos;c&apos; occurs somewhere in the
      word but not at the third place.  Also, the letters &apos;f&apos; and &apos;h&apos;
      do not occur anywhere in the word.  Refine the previous command
      further to add these constraints:
    &lt;/p&gt;
&lt;pre&gt;&lt;samp&gt;$ &lt;kbd&gt;words | grep &apos;[^e]i[^iec][^e]e&apos; | grep c | grep -v &apos;[arosbgfh]&apos; | head -n 5&lt;/kbd&gt;
mince
wince&lt;/samp&gt;&lt;/pre&gt;
    &lt;p&gt;
      Enter the word &quot;mince&quot; for the fourth guess.  It leads to the
      following result:
    &lt;/p&gt;
    &lt;p style=&quot;font-family: monospace; font-weight: bold; color: #ddd&quot;&gt;
      &lt;span style=&quot;background: #333; padding: 0.5em&quot;&gt;M&lt;/span&gt;
      &lt;span style=&quot;background: #585; padding: 0.5em&quot;&gt;I&lt;/span&gt;
      &lt;span style=&quot;background: #585; padding: 0.5em&quot;&gt;N&lt;/span&gt;
      &lt;span style=&quot;background: #585; padding: 0.5em&quot;&gt;C&lt;/span&gt;
      &lt;span style=&quot;background: #585; padding: 0.5em&quot;&gt;E&lt;/span&gt;
    &lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;
      We are almost there!  We now have all the letters except the
      first one.  The previous result shows that the letter &apos;m&apos; does
      not occur in the word.  Thus the answer word must be &quot;wince&quot;.
      For the sake of completeness, here is a refined search that
      selects the answer word based on the constraints known so far:
    &lt;/p&gt;
&lt;pre&gt;&lt;samp&gt;$ &lt;kbd&gt;words | grep &apos;[^e]ince&apos; | grep -v &apos;[arosbgfhm]&apos; | head -n 5&lt;/kbd&gt;
wince&lt;/samp&gt;&lt;/pre&gt;
    &lt;p&gt;
      It looks like we have found the answer word.  Enter &quot;wince&quot; as
      the fifth guess to get the following result:
    &lt;/p&gt;
    &lt;p style=&quot;font-family: monospace; font-weight: bold; color: #ddd&quot;&gt;
      &lt;span style=&quot;background: #585; padding: 0.5em&quot;&gt;W&lt;/span&gt;
      &lt;span style=&quot;background: #585; padding: 0.5em&quot;&gt;I&lt;/span&gt;
      &lt;span style=&quot;background: #585; padding: 0.5em&quot;&gt;N&lt;/span&gt;
      &lt;span style=&quot;background: #585; padding: 0.5em&quot;&gt;C&lt;/span&gt;
      &lt;span style=&quot;background: #585; padding: 0.5em&quot;&gt;E&lt;/span&gt;
    &lt;/p&gt;
    &lt;p&gt;
      Done!
    &lt;/p&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;wordle-218&quot;&gt;Wordle #218&lt;/h2&gt;
&lt;p&gt;
  Now that the wordle for Sat,&amp;nbsp;22&amp;nbsp;Jan&amp;nbsp;2022 is solved,
  let us try the same method on Wordle #219 for
  Sun,&amp;nbsp;23&amp;nbsp;Jan&amp;nbsp;2022 and see how well this method works.
  Here are the steps:
&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;
      Like before, the first guess is &quot;arose&quot;.  Entering this word
      leads to the following result:
    &lt;/p&gt;
    &lt;p style=&quot;font-family: monospace; font-weight: bold; color: #ddd&quot;&gt;
      &lt;span style=&quot;background: #333; padding: 0.5em&quot;&gt;A&lt;/span&gt;
      &lt;span style=&quot;background: #585; padding: 0.5em&quot;&gt;R&lt;/span&gt;
      &lt;span style=&quot;background: #333; padding: 0.5em&quot;&gt;O&lt;/span&gt;
      &lt;span style=&quot;background: #333; padding: 0.5em&quot;&gt;S&lt;/span&gt;
      &lt;span style=&quot;background: #333; padding: 0.5em&quot;&gt;E&lt;/span&gt;
    &lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;
      Now search for words based on the previous result.
    &lt;/p&gt;
&lt;pre&gt;&lt;samp&gt;$ &lt;kbd&gt;words | grep &apos;.r...&apos; | grep -v &apos;[aose]&apos; | head -n 5&lt;/kbd&gt;
brick
bring
brink
briny
bruin&lt;/samp&gt;&lt;/pre&gt;
    &lt;p&gt;
      Enter the word &quot;brick&quot; as the second guess.  This leads to the
      following result:
    &lt;/p&gt;
    &lt;p style=&quot;font-family: monospace; font-weight: bold; color: #ddd&quot;&gt;
      &lt;span style=&quot;background: #333; padding: 0.5em&quot;&gt;B&lt;/span&gt;
      &lt;span style=&quot;background: #585; padding: 0.5em&quot;&gt;R&lt;/span&gt;
      &lt;span style=&quot;background: #585; padding: 0.5em&quot;&gt;I&lt;/span&gt;
      &lt;span style=&quot;background: #b93; padding: 0.5em&quot;&gt;C&lt;/span&gt;
      &lt;span style=&quot;background: #333; padding: 0.5em&quot;&gt;K&lt;/span&gt;
    &lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;
      Use the previous result to refine the search further.
    &lt;/p&gt;
&lt;pre&gt;&lt;samp&gt;$ &lt;kbd&gt;words | grep &apos;.ri[^c].&apos; | grep c | grep -v &apos;[aosebk]&apos; | head -n 5&lt;/kbd&gt;
crimp&lt;/samp&gt;&lt;/pre&gt;
    &lt;p&gt;
      Enter &quot;crimp&quot; as the third guess.  This leads to the following
      result:
    &lt;/p&gt;
    &lt;p style=&quot;font-family: monospace; font-weight: bold; color: #ddd&quot;&gt;
      &lt;span style=&quot;background: #585; padding: 0.5em&quot;&gt;C&lt;/span&gt;
      &lt;span style=&quot;background: #585; padding: 0.5em&quot;&gt;R&lt;/span&gt;
      &lt;span style=&quot;background: #585; padding: 0.5em&quot;&gt;I&lt;/span&gt;
      &lt;span style=&quot;background: #585; padding: 0.5em&quot;&gt;M&lt;/span&gt;
      &lt;span style=&quot;background: #585; padding: 0.5em&quot;&gt;P&lt;/span&gt;
    &lt;/p&gt;
    &lt;p&gt;
      Done!
    &lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;wordle-219&quot;&gt;Wordle #219&lt;/h2&gt;
&lt;p&gt;
  Finally, let us solve Wordle #219 for
  Mon,&amp;nbsp;24&amp;nbsp;Jan&amp;nbsp;2022.
&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;
      Enter &quot;arose&quot; as the first guess to get this result:
    &lt;/p&gt;
    &lt;p style=&quot;font-family: monospace; font-weight: bold; color: #ddd&quot;&gt;
      &lt;span style=&quot;background: #333; padding: 0.5em&quot;&gt;A&lt;/span&gt;
      &lt;span style=&quot;background: #333; padding: 0.5em&quot;&gt;R&lt;/span&gt;
      &lt;span style=&quot;background: #585; padding: 0.5em&quot;&gt;O&lt;/span&gt;
      &lt;span style=&quot;background: #333; padding: 0.5em&quot;&gt;S&lt;/span&gt;
      &lt;span style=&quot;background: #333; padding: 0.5em&quot;&gt;E&lt;/span&gt;
    &lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;
      The previous result shows that the third letter is &apos;o&apos; and the
      letters &apos;a&apos;, &apos;r&apos;, &apos;s&apos; and &apos;e&apos; do not occur anywhere in the word.
      Search for words that match these constraints.
    &lt;/p&gt;
&lt;pre&gt;&lt;samp&gt;$ &lt;kbd&gt;words | grep &apos;..o..&apos; | grep -v &apos;[arse]&apos; | head -n 5&lt;/kbd&gt;
block
blond
blood
bloom
blown&lt;/samp&gt;&lt;/pre&gt;
    &lt;p&gt;
      Enter &quot;block&quot; as the second guess.  This leads to the following
      result:
    &lt;/p&gt;
    &lt;p style=&quot;font-family: monospace; font-weight: bold; color: #ddd&quot;&gt;
      &lt;span style=&quot;background: #333; padding: 0.5em&quot;&gt;B&lt;/span&gt;
      &lt;span style=&quot;background: #b93; padding: 0.5em&quot;&gt;L&lt;/span&gt;
      &lt;span style=&quot;background: #585; padding: 0.5em&quot;&gt;O&lt;/span&gt;
      &lt;span style=&quot;background: #333; padding: 0.5em&quot;&gt;C&lt;/span&gt;
      &lt;span style=&quot;background: #b93; padding: 0.5em&quot;&gt;K&lt;/span&gt;
    &lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;
      The previous result shows that the letter &apos;l&apos; occurs somewhere
      in the word but not at the second place.  Similarly, the letter
      &apos;k&apos; occurs somewhere in the word but not at the fifth place.
      Further, the letters &apos;b&apos; and &apos;c&apos; do not occur anywhere in the
      word.  Search for words that match these constraints.
    &lt;/p&gt;
&lt;pre&gt;&lt;samp&gt;$ &lt;kbd&gt;words | grep &apos;.[^l]o.[^k]&apos; | grep l | grep k | grep -v &apos;[arsebc]&apos; | head -n 5&lt;/kbd&gt;
knoll&lt;/samp&gt;&lt;/pre&gt;
    &lt;p&gt;
      Enter &quot;knoll&quot; as the third guess.  It leads to the following
      result:
    &lt;/p&gt;
    &lt;p style=&quot;font-family: monospace; font-weight: bold; color: #ddd&quot;&gt;
      &lt;span style=&quot;background: #585; padding: 0.5em&quot;&gt;K&lt;/span&gt;
      &lt;span style=&quot;background: #585; padding: 0.5em&quot;&gt;N&lt;/span&gt;
      &lt;span style=&quot;background: #585; padding: 0.5em&quot;&gt;O&lt;/span&gt;
      &lt;span style=&quot;background: #585; padding: 0.5em&quot;&gt;L&lt;/span&gt;
      &lt;span style=&quot;background: #585; padding: 0.5em&quot;&gt;L&lt;/span&gt;
    &lt;/p&gt;
    &lt;p&gt;
      Done!
    &lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;
<!-- ### -->
&lt;p&gt;
  &lt;a href="https://susam.net/wordle-with-grep.html"&gt;Read on website&lt;/a&gt; |
  &lt;a href=&quot;https://susam.net/tag/unix.html&quot;&gt;#unix&lt;/a&gt; |
  &lt;a href=&quot;https://susam.net/tag/shell.html&quot;&gt;#shell&lt;/a&gt; |
  &lt;a href=&quot;https://susam.net/tag/technology.html&quot;&gt;#technology&lt;/a&gt; |
  &lt;a href=&quot;https://susam.net/tag/puzzle.html&quot;&gt;#puzzle&lt;/a&gt;
&lt;/p&gt;
<!-- END HTML -->
    </content>
  </entry>
  <entry>
    <title>Shell Eval</title>
    <link href="https://susam.net/shell-eval.html"/>
    <id>urn:uuid:b06e9411-2efb-4af6-9153-7118a5360f2d</id>
    <updated>2022-01-06T00:00:00Z</updated>
    <content type="html">
<!-- BEGIN HTML -->
&lt;p&gt;
  In this post, we will perform a few experiments to see the
  usefulness of the &lt;code&gt;eval&lt;/code&gt; command for a particular
  scenario in a POSIX-compliant shell.  At first, we prepare a test
  file that contains a space in its name and define a variable as
  follows:
&lt;/p&gt;
&lt;pre&gt;&lt;samp&gt;$ &lt;kbd&gt;echo lorem ipsum &amp;gt; &quot;foo bar&quot;&lt;/kbd&gt;
$ &lt;kbd&gt;cmd=&apos;cat &quot;foo bar&quot;&apos;&lt;/kbd&gt;&lt;/samp&gt;&lt;/pre&gt;
&lt;p&gt;
  We will use this file and the variable in the experiments below.
  All output examples below are obtained using Dash 0.5.11 on a Debian
  GNU/Linux 11.2 (bullseye) system.  Dash stands for Debian Almquist
  Shell which is a POSIX-compliant shell available in Debian.  Any
  POSIX conforming shell should produce similar output.  On Zsh, use
  the command &lt;code&gt;emulate sh&lt;/code&gt; before running these examples to
  get similar output.
&lt;/p&gt;
&lt;h2 id=&quot;experiment-1&quot;&gt;Experiment 1&lt;/h2&gt;
&lt;p&gt;
  Now simply enter &lt;code&gt;$cmd&lt;/code&gt; as a command into the shell.  The
  following error occurs:
&lt;/p&gt;
&lt;pre&gt;&lt;samp&gt;$ &lt;kbd&gt;$cmd&lt;/kbd&gt;
cat: &apos;&quot;foo&apos;: No such file or directory
cat: &apos;bar&quot;&apos;: No such file or directory&lt;/samp&gt;&lt;/pre&gt;
&lt;p&gt;
  The error occurs because the above command expands to the
  command &lt;code&gt;cat&lt;/code&gt; followed by two
  arguments: &lt;code&gt;&quot;foo&lt;/code&gt; and &lt;code&gt;bar&quot;&lt;/code&gt;.  Such an
  expansion occurs due to a concept known as field splitting.  Quoting
  from section 2.6.5 of
  &lt;a href=&quot;https://pubs.opengroup.org/onlinepubs/9699919799/&quot;&gt;POSIX.1-2017&lt;/a&gt;:
&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;
    After parameter expansion, command substitution, and arithmetic
    expansion, the shell shall scan the results of expansions and
    substitutions that did not occur in double-quotes for field
    splitting and multiple fields can result.
  &lt;/p&gt;
  &lt;p&gt;
    The shell shall treat each character of the IFS as a delimiter and
    use the delimiters as field terminators to split the results of
    parameter expansion, command substitution, and arithmetic
    expansion into fields.
  &lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;
  By default, the space character belongs to &lt;code&gt;IFS&lt;/code&gt;.  Here
  is an example command to verify this:
&lt;/p&gt;
&lt;pre&gt;&lt;samp&gt;$ &lt;kbd&gt;printf &quot;$IFS&quot; | od -tcx1&lt;/kbd&gt;
0000000      \t  \n
         20  09  0a
0000003&lt;/samp&gt;&lt;/pre&gt;
&lt;p&gt;
  The hexadecimal code &lt;samp&gt;20&lt;/samp&gt; in the output confirms that the
  space character is present in the value of &lt;code&gt;IFS&lt;/code&gt;.
  Therefore, according to the POSIX specification, &lt;code&gt;$cmd&lt;/code&gt;
  first expands to &lt;code&gt;cat &quot;foo bar&quot;&lt;/code&gt;, then it is split into
  three fields &lt;code&gt;cat&lt;/code&gt;, &lt;code&gt;&quot;foo&lt;/code&gt; and
  &lt;code&gt;bar&quot;&lt;/code&gt; and then the command &lt;code&gt;cat&lt;/code&gt; is executed
  with two arguments &lt;code&gt;&quot;foo&lt;/code&gt; and &lt;code&gt;bar&quot;&lt;/code&gt;.  Since
  no files with those names exist, an error occurs.
&lt;/p&gt;
&lt;h2 id=&quot;experiment-2&quot;&gt;Experiment 2&lt;/h2&gt;
&lt;p&gt;
  Next we try to double-quote the previous command to prevent field
  splitting and see what happens:
&lt;pre&gt;&lt;samp&gt;$ &lt;kbd&gt;&quot;$cmd&quot;&lt;/kbd&gt;
dash: 8: cat &quot;foo bar&quot;: not found&lt;/samp&gt;&lt;/pre&gt;
&lt;p&gt;
  The excerpt from the POSIX.1-2017 specification quoted in the
  previous section shows that field splitting does not occur for
  variable expansions within double quotes.  So the entire
  expansion &lt;code&gt;cat &quot;foo bar&quot;&lt;/code&gt; remains intact as a single
  field and is then executed as a command.  Since there is no such
  weirdly named command, we get the above error.
&lt;/p&gt;
&lt;h2 id=&quot;experiment-3&quot;&gt;Experiment 3&lt;/h2&gt;
&lt;p&gt;
  Field splitting leads to an error as seen in the first experiment.
  Preventing field splitting by double-quoting the variable expansion
  also leads to an error as seen in the second experiment.  How do we
  execute the command in the &lt;code&gt;cmd&lt;/code&gt; variable?
&lt;/p&gt;
&lt;p&gt;
  We need a way to somehow get the shell to parse &lt;code&gt;cat &quot;foo
  bar&quot;&lt;/code&gt; like a shell normally does, i.e. treat each unquoted
  token as a separate field and each quoted token as a single one.
  How do we get the shell to do that?  Well, we can just invoke the
  shell itself to parse our command:
&lt;/p&gt;
&lt;pre&gt;&lt;samp&gt;$ &lt;kbd&gt;sh -c &quot;$cmd&quot;&lt;/kbd&gt;
lorem ipsum&lt;/samp&gt;&lt;/pre&gt;
&lt;p&gt;
  But the above command invokes a new shell process.  Can we avoid
  that?  Yes, using the &lt;code&gt;eval&lt;/code&gt; command:
&lt;/p&gt;
&lt;pre&gt;&lt;samp&gt;$ &lt;kbd&gt;eval &quot;$cmd&quot;&lt;/kbd&gt;
lorem ipsum&lt;/samp&gt;&lt;/pre&gt;
<!-- ### -->
&lt;p&gt;
  &lt;a href="https://susam.net/shell-eval.html"&gt;Read on website&lt;/a&gt; |
  &lt;a href=&quot;https://susam.net/tag/unix.html&quot;&gt;#unix&lt;/a&gt; |
  &lt;a href=&quot;https://susam.net/tag/shell.html&quot;&gt;#shell&lt;/a&gt; |
  &lt;a href=&quot;https://susam.net/tag/technology.html&quot;&gt;#technology&lt;/a&gt;
&lt;/p&gt;
<!-- END HTML -->
    </content>
  </entry>
  <entry>
    <title>Of Course "changeme" Is Valid Base64</title>
    <link href="https://susam.net/of-course-changeme-is-valid-base64.html"/>
    <id>urn:uuid:fbcc9953-15ca-44c6-a4b6-31838ab3e242</id>
    <updated>2020-10-24T00:00:00Z</updated>
    <content type="html">
<!-- BEGIN HTML -->
&lt;p&gt;
  Today, I came across
  this &lt;a href=&quot;https://3fx.ch/blog/2019/12/09/changeme-is-valid-base64/&quot;&gt;blog
  post&lt;/a&gt; regarding how the author of the post used the
  string &lt;code&gt;&quot;changeme&quot;&lt;/code&gt; as test data while testing a Base64
  decoding functionality in their application.  However, the author
  incorrectly believed that this test data is not a valid
  Base64-encoded string and therefore would fail to decode
  successfully when decoded as Base64.  To their surprise, they found
  that this string &lt;code&gt;&quot;changeme&quot;&lt;/code&gt; does in fact decode
  successfully.
&lt;/p&gt;
&lt;p&gt;
  The post did not go any further into understanding why
  indeed &lt;code&gt;&quot;changeme&quot;&lt;/code&gt; is a valid Base64-encoded string and
  why it can successfully be decoded into binary data.  It appears
  that the author was using Base64 encoding scheme as a black box.
&lt;/p&gt;
&lt;p&gt;
  I think it is worth noting and illustrating that any alphanumeric
  string with a length that is a multiple of 4 is a valid
  Base64-encoded string.  Here are some examples that illustrate this:
&lt;/p&gt;
&lt;pre&gt;&lt;samp&gt;$ &lt;kbd&gt;printf AAAA | base64 --decode | od -tx1&lt;/kbd&gt;
0000000    00  00  00
0000003
$ &lt;kbd&gt;printf AAAAAAAA | base64 --decode | od -tx1&lt;/kbd&gt;
0000000    00  00  00  00  00  00
0000006
$ &lt;kbd&gt;printf AQEB | base64 --decode | od -tx1&lt;/kbd&gt;
0000000    01  01  01
0000003
$ &lt;kbd&gt;printf AQID | base64 --decode | od -tx1&lt;/kbd&gt;
0000000    01  02  03
0000003
$ &lt;kbd&gt;printf main | base64 --decode | od -tx1&lt;/kbd&gt;
0000000    99  a8  a7
0000003
$ &lt;kbd&gt;printf scrabble | base64 --decode | od -tx1&lt;/kbd&gt;
0000000    b1  ca  da  6d  b9  5e
0000006
$ &lt;kbd&gt;printf 12345678 | base64 --decode | od -tx1&lt;/kbd&gt;
0000000    d7  6d  f8  e7  ae  fc
0000006&lt;/samp&gt;&lt;/pre&gt;
&lt;p&gt;
  Further, since &lt;code&gt;+&lt;/code&gt; and &lt;code&gt;/&lt;/code&gt; are also used as
  symbols in Base64 encoding (for binary &lt;code&gt;111110&lt;/code&gt;
  and &lt;code&gt;111111&lt;/code&gt; respectively), we also have a few more
  interesting examples:
&lt;/p&gt;
&lt;pre&gt;&lt;samp&gt;$ &lt;kbd&gt;printf 1+2+3+4+5/11 | base64 --decode | od -tx1&lt;/kbd&gt;
0000000    d7  ed  be  df  ee  3e  e7  fd  75
0000011
$ &lt;kbd&gt;printf &quot;\xd7\xed\xbe\xdf\xee\x3e\xe7\xfd\x75&quot; | base64&lt;/kbd&gt;
1+2+3+4+5/11&lt;/samp&gt;&lt;/pre&gt;
&lt;p&gt;
  I think it is good to understand why any string with a length that
  is a multiple of 4 turns out to be a valid Base64-encoded string.
  The Base64 encoding scheme encodes each group of 6 bits in the
  binary input with a chosen ASCII character.  For every possible
  6-bit binary value, we have assigned an ASCII character that appears
  in the Base64-encoded string.  Each output ASCII character can be
  one of the 64 carefully chosen ASCII characters: lowercase and
  uppercase letters from the English alphabet, the ten digits from the
  Arabic numerals, the plus sign (&lt;code&gt;+&lt;/code&gt;) and the forward
  slash (&lt;code&gt;/&lt;/code&gt;).  For example, the bits &lt;code&gt;000000&lt;/code&gt;
  is encoded as &lt;code&gt;A&lt;/code&gt;, the bits &lt;code&gt;000001&lt;/code&gt; is
  encoded as &lt;code&gt;B&lt;/code&gt; and so on.  The equals sign
  (&lt;code&gt;=&lt;/code&gt;) is used for padding but that is not something we
  will discuss in detail in this post.
&lt;/p&gt;
&lt;p&gt;
  The smallest positive multiple of 6 that is also a multiple of 8 is
  24.  Thus every group of 3 bytes (24 bits) of binary data is
  translated to 4 ASCII characters in its Base64-encoded string.  Thus
  the entire input data is divided into groups of 3 bytes each and
  then each group of 3 bytes is encoded into 4 ASCII characters.  What
  if the last group is less than 3 bytes long?  There are certain
  padding rules for such cases but I will not discuss them right now
  in this post.  For more details on the padding rules,
  see &lt;a href=&quot;https://www.rfc-editor.org/rfc/rfc4648&quot;&gt;RFC 4648&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
  Now as a natural result of the encoding scheme, it turns out that
  any 4 alphanumeric characters is a valid Base64 encoding of some
  binary data.  That&apos;s because for every alphanumeric character, we
  can find some 6-bit binary data that would be translated to it
  during Base64 encoding.  This is the reason why any alphanumeric
  string with a length that is a multiple of 4 is a valid
  Base64-encoded string and can be successfully decoded to some binary
  data.
&lt;/p&gt;

<!-- ### -->
&lt;p&gt;
  &lt;a href="https://susam.net/of-course-changeme-is-valid-base64.html"&gt;Read on website&lt;/a&gt; |
  &lt;a href=&quot;https://susam.net/tag/unix.html&quot;&gt;#unix&lt;/a&gt; |
  &lt;a href=&quot;https://susam.net/tag/shell.html&quot;&gt;#shell&lt;/a&gt; |
  &lt;a href=&quot;https://susam.net/tag/technology.html&quot;&gt;#technology&lt;/a&gt;
&lt;/p&gt;
<!-- END HTML -->
    </content>
  </entry>
  <entry>
    <title>Unix Timestamp 1600000000</title>
    <link href="https://susam.net/unix-timestamp-1600000000.html"/>
    <id>urn:uuid:6e3c2f3d-6dec-4215-909c-f19ab0a4f4ac</id>
    <updated>2020-09-12T00:00:00Z</updated>
    <content type="html">
<!-- BEGIN HTML -->
&lt;p&gt;
  At 2020-09-13 12:26:40 UTC, the Unix timestamp is going to turn
  1600000000.
&lt;/p&gt;
&lt;h2 id=&quot;unix-timestamp-conversion&quot;&gt;Unix Timestamp Conversion&lt;/h2&gt;
&lt;p&gt;
  The following subsections show a few examples of converting the Unix
  timestamp to a human-readable date.
&lt;/p&gt;
&lt;h3 id=&quot;python&quot;&gt;Python&lt;/h3&gt;
&lt;pre&gt;&lt;samp&gt;$ &lt;kbd&gt;python3 -q&lt;/kbd&gt;
&amp;gt;&amp;gt;&amp;gt; &lt;kbd&gt;from datetime import datetime&lt;/kbd&gt;
&amp;gt;&amp;gt;&amp;gt; &lt;kbd&gt;datetime.utcfromtimestamp(1_600_000_000)&lt;/kbd&gt;
datetime.datetime(2020, 9, 13, 12, 26, 40)&lt;/samp&gt;&lt;/pre&gt;
&lt;h3 id=&quot;gnu-date&quot;&gt;GNU date (Linux)&lt;/h3&gt;
&lt;pre&gt;&lt;samp&gt;$ &lt;kbd&gt;date -ud @1600000000&lt;/kbd&gt;
Sun Sep 13 12:26:40 UTC 2020&lt;/samp&gt;&lt;/pre&gt;
&lt;h3 id=&quot;bsd-date&quot;&gt;BSD date (macOS, FreeBSD, OpenBSD, etc.)&lt;/h3&gt;
&lt;pre&gt;&lt;samp&gt;$ &lt;kbd&gt;date -ur 1600000000&lt;/kbd&gt;
Sun Sep 13 12:26:40 UTC 2020&lt;/samp&gt;&lt;/pre&gt;
&lt;h2 id=&quot;other-such-dates&quot;&gt;Other Such Dates&lt;/h2&gt;
&lt;p&gt;
  All such dates (in UTC) until the end of the current century:
&lt;/p&gt;
&lt;pre&gt;&lt;samp&gt;$ &lt;kbd&gt;python3 -q&lt;/kbd&gt;
&amp;gt;&amp;gt;&amp;gt; &lt;kbd&gt;from datetime import datetime&lt;/kbd&gt;
&amp;gt;&amp;gt;&amp;gt; &lt;kbd&gt;for t in range(0, 4_200_000_000, 100_000_000):&lt;/kbd&gt;
... &lt;kbd&gt;    print(f&apos;{t:13_d} - {datetime.utcfromtimestamp(t)}&apos;)&lt;/kbd&gt;
...
            0 - 1970-01-01 00:00:00
  100_000_000 - 1973-03-03 09:46:40
  200_000_000 - 1976-05-03 19:33:20
  300_000_000 - 1979-07-05 05:20:00
  400_000_000 - 1982-09-04 15:06:40
  500_000_000 - 1985-11-05 00:53:20
  600_000_000 - 1989-01-05 10:40:00
  700_000_000 - 1992-03-07 20:26:40
  800_000_000 - 1995-05-09 06:13:20
  900_000_000 - 1998-07-09 16:00:00
1_000_000_000 - 2001-09-09 01:46:40
1_100_000_000 - 2004-11-09 11:33:20
1_200_000_000 - 2008-01-10 21:20:00
1_300_000_000 - 2011-03-13 07:06:40
1_400_000_000 - 2014-05-13 16:53:20
1_500_000_000 - 2017-07-14 02:40:00
1_600_000_000 - 2020-09-13 12:26:40
1_700_000_000 - 2023-11-14 22:13:20
1_800_000_000 - 2027-01-15 08:00:00
1_900_000_000 - 2030-03-17 17:46:40
2_000_000_000 - 2033-05-18 03:33:20
2_100_000_000 - 2036-07-18 13:20:00
2_200_000_000 - 2039-09-18 23:06:40
2_300_000_000 - 2042-11-19 08:53:20
2_400_000_000 - 2046-01-19 18:40:00
2_500_000_000 - 2049-03-22 04:26:40
2_600_000_000 - 2052-05-22 14:13:20
2_700_000_000 - 2055-07-24 00:00:00
2_800_000_000 - 2058-09-23 09:46:40
2_900_000_000 - 2061-11-23 19:33:20
3_000_000_000 - 2065-01-24 05:20:00
3_100_000_000 - 2068-03-26 15:06:40
3_200_000_000 - 2071-05-28 00:53:20
3_300_000_000 - 2074-07-28 10:40:00
3_400_000_000 - 2077-09-27 20:26:40
3_500_000_000 - 2080-11-28 06:13:20
3_600_000_000 - 2084-01-29 16:00:00
3_700_000_000 - 2087-04-01 01:46:40
3_800_000_000 - 2090-06-01 11:33:20
3_900_000_000 - 2093-08-01 21:20:00
4_000_000_000 - 2096-10-02 07:06:40
4_100_000_000 - 2099-12-03 16:53:20&lt;/samp&gt;&lt;/pre&gt;
&lt;h2 id=&quot;update&quot;&gt;Update&lt;/h2&gt;
&lt;p&gt;
  Here is a screenshot I took at Unix timestamp 1600000000:
  &lt;a href=&quot;https://twitter.com/susam/status/1305120936098627589&quot;&gt;twitter.com/susam/status/130512093609862758&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
  Reproduced as text below:
&lt;/p&gt;
&lt;pre&gt;&lt;samp&gt;$ &lt;kbd&gt;date -u; date; date +%s&lt;/kbd&gt;
Sun Sep 13 12:26:39 UTC 2020
Sun Sep 13 17:56:39 IST 2020
1599999999
$ &lt;kbd&gt;date -u; date; date +%s&lt;/kbd&gt;
Sun Sep 13 12:26:40 UTC 2020
Sun Sep 13 17:56:40 IST 2020
1600000000&lt;/samp&gt;&lt;/pre&gt;
&lt;p&gt;
  An important point worth noting from the POSIX.1-2008 specification:
&lt;/p&gt;
&lt;blockquote&gt;
  Coordinated Universal Time (UTC) includes leap seconds.  However, in
  POSIX time (seconds since the Epoch), leap seconds are ignored (not
  applied) to provide an easy and compatible method of computing time
  differences.  Broken-down POSIX time is therefore not necessarily
  UTC, despite its appearance.
&lt;/blockquote&gt;
&lt;p&gt;
  See &lt;a href=&quot;https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_xbd_chap04.html#tag_21_04_16&quot;&gt;&amp;sect; A.4.16&lt;/a&gt;
  of the POSIX.1-2008 specification for more details.
&lt;/p&gt;
<!-- ### -->
&lt;p&gt;
  &lt;a href="https://susam.net/unix-timestamp-1600000000.html"&gt;Read on website&lt;/a&gt; |
  &lt;a href=&quot;https://susam.net/tag/unix.html&quot;&gt;#unix&lt;/a&gt; |
  &lt;a href=&quot;https://susam.net/tag/shell.html&quot;&gt;#shell&lt;/a&gt; |
  &lt;a href=&quot;https://susam.net/tag/python.html&quot;&gt;#python&lt;/a&gt; |
  &lt;a href=&quot;https://susam.net/tag/programming.html&quot;&gt;#programming&lt;/a&gt; |
  &lt;a href=&quot;https://susam.net/tag/technology.html&quot;&gt;#technology&lt;/a&gt;
&lt;/p&gt;
<!-- END HTML -->
    </content>
  </entry>
  <entry>
    <title>Unix Line Discard</title>
    <link href="https://susam.net/unix-line-discard.html"/>
    <id>urn:uuid:c78208c6-42fe-4681-82aa-ee91e25208d8</id>
    <updated>2017-07-09T00:00:00Z</updated>
    <content type="html">
<!-- BEGIN HTML -->
&lt;p&gt;
  Type &lt;code&gt;C-u&lt;/code&gt; (i.e. &lt;kbd&gt;ctrl&lt;/kbd&gt;+&lt;kbd&gt;u&lt;/kbd&gt;) in Bash or
  Zsh to discard the current line of input.  To read more about it,
  enter &lt;code&gt;man bash&lt;/code&gt; and then type
  &lt;code&gt;/unix-line-discard&lt;/code&gt; to locate the relevant section of
  the manual.  Here is an excerpt:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;unix-line-discard (C-u)
       Kill backward from point to the beginning of the line.
       The killed text is saved on the kill-ring.&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
  Similarly, for Zsh, type &lt;code&gt;man zshzle&lt;/code&gt; and then
  type &lt;code&gt;/kill-whole-line&lt;/code&gt;.  We find this:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;kill-whole-line (^U) (unbound) (unbound)
       Kill the current line.&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
  By the way, Emacs-style key sequence like &lt;code&gt;C-a C-k&lt;/code&gt; works
  too.
&lt;/p&gt;
&lt;p&gt;
  Furthermore, it is quite likely that &lt;code&gt;C-u&lt;/code&gt; is mapped to
  delete the current line of input in the terminal itself.  To confirm
  this, type the command &lt;code&gt;stty -a&lt;/code&gt; and check the output.
  If the output contains the text &lt;code&gt;kill = ^U&lt;/code&gt;, then
  typing &lt;code&gt;C-u&lt;/code&gt; anytime in the terminal would delete the
  current line of input.  This would happen regardless of what program
  is running in the terminal.  For example, programs
  like &lt;code&gt;cat&lt;/code&gt;, &lt;code&gt;sbcl&lt;/code&gt;, etc. do not support key
  sequences like &lt;code&gt;C-a&lt;/code&gt;, &lt;code&gt;C-k&lt;/code&gt;, &lt;code&gt;C-u&lt;/code&gt;,
  etc. the way Bash or Zsh does.  Despite this limitation,
  typing &lt;code&gt;C-u&lt;/code&gt; in &lt;code&gt;cat&lt;/code&gt; or &lt;code&gt;sbcl&lt;/code&gt;
  would delete the current line of input if the output of &lt;code&gt;stty
  -a&lt;/code&gt; indicates that the terminal has mapped this key sequence
  to the operation of deleting the current line.
&lt;/p&gt;
<!-- ### -->
&lt;p&gt;
  &lt;a href="https://susam.net/unix-line-discard.html"&gt;Read on website&lt;/a&gt; |
  &lt;a href=&quot;https://susam.net/tag/unix.html&quot;&gt;#unix&lt;/a&gt; |
  &lt;a href=&quot;https://susam.net/tag/shell.html&quot;&gt;#shell&lt;/a&gt; |
  &lt;a href=&quot;https://susam.net/tag/technology.html&quot;&gt;#technology&lt;/a&gt;
&lt;/p&gt;
<!-- END HTML -->
    </content>
  </entry>
  <entry>
    <title>Random String in Shell</title>
    <link href="https://susam.net/random-string-in-shell.html"/>
    <id>urn:uuid:6dde1077-33c9-46c8-a27c-4414f7f71930</id>
    <updated>2011-08-11T00:00:00Z</updated>
    <content type="html">
<!-- BEGIN HTML -->
&lt;p&gt;
  Here is a quick way to generate a random alphanumeric string in the
  shell:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;LC_CTYPE=C tr -dc &apos;[:alnum:]&apos; &amp;lt; /dev/urandom | head -c 20; echo&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
  Here is an example output:
&lt;/p&gt;
&lt;pre&gt;&lt;samp&gt;GrWPmvF1oOmbeUzyJwC3&lt;/samp&gt;&lt;/pre&gt;
&lt;p&gt;
  The command works both on macOS as well as Linux.
  The &lt;code&gt;LC_CTYPE=C&lt;/code&gt; environment variable is set specifically
  to make the command work successfully on macOS.  Without
  it &lt;code&gt;tr&lt;/code&gt; may report an &quot;Illegal byte sequence&quot; error.
&lt;/p&gt;
<!-- ### -->
&lt;p&gt;
  &lt;a href="https://susam.net/random-string-in-shell.html"&gt;Read on website&lt;/a&gt; |
  &lt;a href=&quot;https://susam.net/tag/unix.html&quot;&gt;#unix&lt;/a&gt; |
  &lt;a href=&quot;https://susam.net/tag/shell.html&quot;&gt;#shell&lt;/a&gt; |
  &lt;a href=&quot;https://susam.net/tag/technology.html&quot;&gt;#technology&lt;/a&gt;
&lt;/p&gt;
<!-- END HTML -->
    </content>
  </entry>
  <entry>
    <title>Fork Bunny</title>
    <link href="https://susam.net/fork-bunny.html"/>
    <id>urn:uuid:34f57748-ee06-4f8f-9ec5-23b63c2caa7e</id>
    <updated>2006-06-11T00:00:00Z</updated>
    <content type="html">
<!-- BEGIN HTML -->
&lt;p&gt;
  Have a close look at this line of shell command that can be executed
  on Bash, Zsh and most POSIX or POSIX-like shells:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;: () { : | : &amp;amp; } ; :&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
  Beware!  Don&apos;t execute it on your system without understanding the
  consequences completely.  If the command above looks puzzling, that
  is because it is deliberately obfuscated.  Let us simplify it.
&lt;/p&gt;
&lt;p&gt;
  The &lt;code&gt;:&lt;/code&gt; is a function name.  It could very well have
  been &lt;code&gt;f&lt;/code&gt;.  Let us replace &lt;code&gt;:&lt;/code&gt;
  with &lt;code&gt;f&lt;/code&gt; and see what the code now looks like.
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;f () { f | f &amp;amp; } ; f&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
  Now it looks familiar.  We have two commands separated by a
  semicolon.  Written in a more legible manner, the code would look
  like this:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;f()
{
    f | f &amp;amp;
}

f&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
  It creates a function &lt;code&gt;f&lt;/code&gt; and then executes it.  This
  function calls itself twice recursively.  The control
  operator &lt;code&gt;&amp;amp;&lt;/code&gt; executes the recursive calls
  to &lt;code&gt;f&lt;/code&gt; asynchronously, i.e. in the background.  The
  number of instances of the function executing keeps growing
  exponentially thereby depleting CPU cycles and memory.  The system
  is rendered unusable soon.
&lt;/p&gt;
&lt;p&gt;
  This type of denial-of-service attack by self-replication is also
  known as a &lt;em&gt;fork bunny&lt;/em&gt; which is a specific type
  of &lt;em&gt;wabbit&lt;/em&gt;.  See the following entry in the Jargon File for
  more information on this:
  &lt;a href=&quot;http://catb.org/~esr/jargon/html/W/wabbit.html&quot;&gt;wabbit&lt;/a&gt;.
&lt;/p&gt;
<!-- ### -->
&lt;p&gt;
  &lt;a href="https://susam.net/fork-bunny.html"&gt;Read on website&lt;/a&gt; |
  &lt;a href=&quot;https://susam.net/tag/unix.html&quot;&gt;#unix&lt;/a&gt; |
  &lt;a href=&quot;https://susam.net/tag/shell.html&quot;&gt;#shell&lt;/a&gt; |
  &lt;a href=&quot;https://susam.net/tag/technology.html&quot;&gt;#technology&lt;/a&gt;
&lt;/p&gt;
<!-- END HTML -->
    </content>
  </entry>
  <entry>
    <title>Vim Sudo Write Trick</title>
    <link href="https://susam.net/vim-sudo-write-trick.html"/>
    <id>urn:uuid:69a7c1b8-0ecd-4660-8585-9b97d711dd44</id>
    <updated>2005-08-25T00:00:00Z</updated>
    <content type="html">
<!-- BEGIN HTML -->
&lt;h2 id=&quot;trick&quot;&gt;The Trick&lt;/h2&gt;
&lt;p&gt;
  You open a file, edit it and save it only to get the E45 error
  message that says:
&lt;/p&gt;
&lt;pre&gt;&lt;samp&gt;E45: &apos;readonly&apos; option is set (add ! to override)&lt;/samp&gt;&lt;/pre&gt;
&lt;p&gt;
  You now realise that only root can edit the file.  What do you?
  Start over?  No, instead try this:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;:w !sudo tee &quot;%&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
  I learnt this trick recently from the comment section
  of &lt;a href=&quot;https://web.archive.org/web/20051120054527/http://www.vim.org/tips/tip.php?tip_id=975&quot;&gt;Tip
  #975&lt;/a&gt; on the Vim Tips website.
&lt;/p&gt;
&lt;h2 id=&quot;explanation&quot;&gt;Explanation&lt;/h2&gt;
&lt;p&gt;
  How does the &lt;code&gt;:w !sudo tee &quot;%&quot;&lt;/code&gt; trick work?  Let us look
  at the command part-by-part:
&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code&gt;:w !{cmd}&lt;/code&gt;&lt;/p&gt;
    &lt;p&gt;
      Execute &lt;code&gt;{cmd}&lt;/code&gt; with all lines in buffer as standard
      input.
    &lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code&gt;&quot;%&quot;&lt;/code&gt;&lt;/p&gt;
    &lt;p&gt;
      The &lt;code&gt;%&lt;/code&gt; is replaced with the current filename.  The
      quotes around it keeps the filename as a single argument even if
      it contains whitespace.
    &lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code&gt;tee {file}&lt;/code&gt;&lt;/p&gt;
    &lt;p&gt;
      The &lt;code&gt;tee&lt;/code&gt; command is a Unix command (not a Vim
      command).  It copies standard input to standard output
      and &lt;code&gt;{file}&lt;/code&gt;.
    &lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;more&quot;&gt;More Information&lt;/h2&gt;
&lt;p&gt;
  For more information on this command, enter the following commands
  in Vim:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;:help :w_c
:help current-file
:help :_%&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
  Also, enter the following command in shell:
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;man tee&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;
  I hope this was fun!
&lt;/p&gt;
<!-- ### -->
&lt;p&gt;
  &lt;a href="https://susam.net/vim-sudo-write-trick.html"&gt;Read on website&lt;/a&gt; |
  &lt;a href=&quot;https://susam.net/tag/vim.html&quot;&gt;#vim&lt;/a&gt; |
  &lt;a href=&quot;https://susam.net/tag/unix.html&quot;&gt;#unix&lt;/a&gt; |
  &lt;a href=&quot;https://susam.net/tag/technology.html&quot;&gt;#technology&lt;/a&gt; |
  &lt;a href=&quot;https://susam.net/tag/how-to.html&quot;&gt;#how-to&lt;/a&gt;
&lt;/p&gt;
<!-- END HTML -->
    </content>
  </entry>
  <entry>
    <title>Cal 9 1752</title>
    <link href="https://susam.net/cal-9-1752.html"/>
    <id>urn:uuid:8e8558bf-fa00-4c06-b9c5-009c9a7cc4be</id>
    <updated>2004-09-14T00:00:00Z</updated>
    <content type="html">
<!-- BEGIN HTML -->
&lt;p&gt;
  A very interesting thing I came across recently while learning Unix
  is an apparent gap in the calendar for Sep 1752.  Here is how
  the &lt;code&gt;cal&lt;/code&gt; output for this month appears on a Unix or
  Linux system:
&lt;/p&gt;
&lt;pre&gt;&lt;samp&gt;$ &lt;kbd&gt;cal 9 1752&lt;/kbd&gt;
   September 1752
Su Mo Tu We Th Fr Sa
       1  2 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30&lt;/samp&gt;&lt;/pre&gt;
&lt;p&gt;
  In the SunOS 5.9 manual page
  for &lt;a href=&quot;https://docs.oracle.com/cd/E19683-01/817-3936/6mjgdbv29/index.html&quot;&gt;cal(1)&lt;/a&gt;,
  this gap is explained as follows:
&lt;/p&gt;
&lt;!-- SunOS 5.9 was released on 28 May 2002 --&gt;
&lt;blockquote&gt;
  An unusual calendar is printed for September 1752.  That is the
  month 11 days were skipped to make up for lack of leap year
  adjustments.  To see this calendar, type: &lt;code&gt;cal 9 1752&lt;/code&gt;
&lt;/blockquote&gt;
&lt;p&gt;
  Similarly, FreeBSD 5.0 has the following note in its manual page
  for &lt;a href=&quot;https://www.freebsd.org/cgi/man.cgi?query=cal&amp;amp;sektion=1&amp;amp;manpath=FreeBSD+5.0-RELEASE&quot;&gt;cal(1)&lt;/a&gt;:
&lt;/p&gt;
&lt;!-- FreeBSD 5.0-RELEASE was released in Jan 2003 --&gt;
&lt;blockquote&gt;
  &lt;p&gt;
    -s &lt;em&gt;country_code&lt;/em&gt;
  &lt;/p&gt;
  &lt;p style=&quot;margin-left: 2em&quot;&gt;
    Assume the switch from Julian to Gregorian Calendar at the date
    associated with the &lt;em&gt;country_code&lt;/em&gt;.  If not
    specified, &lt;strong&gt;ncal&lt;/strong&gt; tries to guess the switch date
    from the local environment or falls back to September 2, 1752.
    This was when Great Britain and her colonies switched to the
    Gregorian Calendar.
  &lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;
  On investigating this switch from Julian to Gregorian calendar, I
  learnt that the Julian calendar was introduced by Julius Caesar in
  46 BC and it remained in effect across most of the Western world
  from 45 BC to 1582.  It assumed an average year to be 365.25 days
  long.  However, the actual solar year has been known to be around
  365.2422 days since the 17th century.  Although the difference
  appears to be too small, it leads to an error of adding 1 extra day
  every 128 years.  To reduce this error, the Gregorian calendar was
  introduced in October 1582 by Pope Gregory XIII.  It assumed an
  average year to be 365.2425 days long.
&lt;/p&gt;
&lt;p&gt;
  The new calendar was adopted in some European countries where 4 Oct
  1582 was followed by 15 Oct 1582 thereby skipping 10 days in
  between.  However, it took as long as September 1752 for the new
  calendar to be adopted by Britain.  In Great Britain and the British
  Empire, 2 Sep 1752 was followed by 14 Sep 1752 and that is the gap
  of 11 days we see in the &lt;code&gt;cal 9 1752&lt;/code&gt; output.
&lt;/p&gt;
<!-- ### -->
&lt;p&gt;
  &lt;a href="https://susam.net/cal-9-1752.html"&gt;Read on website&lt;/a&gt; |
  &lt;a href=&quot;https://susam.net/tag/unix.html&quot;&gt;#unix&lt;/a&gt; |
  &lt;a href=&quot;https://susam.net/tag/technology.html&quot;&gt;#technology&lt;/a&gt;
&lt;/p&gt;
<!-- END HTML -->
    </content>
  </entry>
</feed>
