|
5 | 5 | <link href="https://learnbyexample.github.io/atom.xml" rel="self" type="application/atom+xml"/>
|
6 | 6 | <link href="https://learnbyexample.github.io"/>
|
7 | 7 | <generator uri="https://www.getzola.org/">Zola</generator>
|
8 |
| - <updated>2022-06-22T00:00:00+00:00</updated> |
| 8 | + <updated>2022-06-29T00:00:00+00:00</updated> |
9 | 9 | <id>https://learnbyexample.github.io/atom.xml</id>
|
| 10 | + <entry xml:lang="en"> |
| 11 | + <title>CLI tip 12: squeeze empty lines</title> |
| 12 | + <published>2022-06-29T00:00:00+00:00</published> |
| 13 | + <updated>2022-06-29T00:00:00+00:00</updated> |
| 14 | + <link href="https://learnbyexample.github.io/tips/cli-tip-12/" type="text/html"/> |
| 15 | + <id>https://learnbyexample.github.io/tips/cli-tip-12/</id> |
| 16 | + <content type="html"><p><code>awk</code> has a builtin feature to process input content paragraph wise (by setting <code>RS</code> to an empty string). But, did you know that <code>cat</code>, <code>less</code> and <code>grep</code> can also be used to squeeze empty lines?</p> |
| 17 | +<p><code>cat -s</code> (and <code>less -s</code>) will squeeze multiple empty lines in the input to a single empty line in the output. Here's an example:</p> |
| 18 | +<pre style="background-color:#f5f5f5;"> |
| 19 | +<code><span style="color:#1f1f1f;">$ cat ip.txt |
| 20 | +hello |
| 21 | + |
| 22 | + |
| 23 | + |
| 24 | + |
| 25 | +world |
| 26 | + |
| 27 | +apple |
| 28 | +banana |
| 29 | +cherry |
| 30 | + |
| 31 | + |
| 32 | +tea coffee |
| 33 | +chocolate |
| 34 | +$ cat </span><span style="color:#72ab00;">-</span><span style="color:#1f1f1f;">s ip.txt |
| 35 | +hello |
| 36 | + |
| 37 | +world |
| 38 | + |
| 39 | +apple |
| 40 | +banana |
| 41 | +cherry |
| 42 | + |
| 43 | +tea coffee |
| 44 | +chocolate |
| 45 | +</span></code></pre> |
| 46 | +<p>Here's an example with empty lines at the start/end of the input:</p> |
| 47 | +<pre style="background-color:#f5f5f5;"> |
| 48 | +<code><span style="color:#1f1f1f;">$ </span><span style="color:#b39f04;">printf </span><span style="color:#d07711;">&#39;\n\n\ndragon\n\n\nunicorn\n\n\n&#39;</span><span style="color:#1f1f1f;"> |
| 49 | + |
| 50 | + |
| 51 | + |
| 52 | +dragon |
| 53 | + |
| 54 | + |
| 55 | +unicorn |
| 56 | + |
| 57 | + |
| 58 | +$ </span><span style="color:#b39f04;">printf </span><span style="color:#d07711;">&#39;\n\n\ndragon\n\n\nunicorn\n\n\n&#39; </span><span style="color:#72ab00;">|</span><span style="color:#1f1f1f;"> cat </span><span style="color:#72ab00;">-</span><span style="color:#1f1f1f;">s |
| 59 | + |
| 60 | +dragon |
| 61 | + |
| 62 | +unicorn |
| 63 | + |
| 64 | +</span></code></pre> |
| 65 | +<p>And here's a solution with <code>awk</code>. Unlike the <code>-s</code> option, this will completely remove empty lines at the start/end of the input.</p> |
| 66 | +<pre style="background-color:#f5f5f5;"> |
| 67 | +<code><span style="color:#1f1f1f;">$ awk </span><span style="color:#72ab00;">-</span><span style="color:#1f1f1f;">v </span><span style="color:#c23f31;">RS</span><span style="color:#72ab00;">= </span><span style="color:#d07711;">&#39;{print s $0; s=&quot;\n&quot;}&#39;</span><span style="color:#1f1f1f;"> ip.txt |
| 68 | +hello |
| 69 | + |
| 70 | +world |
| 71 | + |
| 72 | +apple |
| 73 | +banana |
| 74 | +cherry |
| 75 | + |
| 76 | +tea coffee |
| 77 | +chocolate |
| 78 | + |
| 79 | +$ </span><span style="color:#b39f04;">printf </span><span style="color:#d07711;">&#39;\n\n\ndragon\n\n\nunicorn\n\n\n&#39; </span><span style="color:#72ab00;">|</span><span style="color:#1f1f1f;"> awk </span><span style="color:#72ab00;">-</span><span style="color:#1f1f1f;">v </span><span style="color:#c23f31;">RS</span><span style="color:#72ab00;">= </span><span style="color:#d07711;">&#39;{print s $0; s=&quot;\n&quot;}&#39;</span><span style="color:#1f1f1f;"> |
| 80 | +dragon |
| 81 | + |
| 82 | +unicorn |
| 83 | +</span></code></pre> |
| 84 | +<p>The <code>awk</code> solution would be easier to extend, given its programmable features. For example, two empty lines between the groups:</p> |
| 85 | +<pre style="background-color:#f5f5f5;"> |
| 86 | +<code><span style="color:#1f1f1f;">$ awk </span><span style="color:#72ab00;">-</span><span style="color:#1f1f1f;">v </span><span style="color:#c23f31;">RS</span><span style="color:#72ab00;">= </span><span style="color:#d07711;">&#39;{print s $0; s=&quot;\n\n&quot;}&#39;</span><span style="color:#1f1f1f;"> ip.txt |
| 87 | +hello |
| 88 | + |
| 89 | + |
| 90 | +world |
| 91 | + |
| 92 | + |
| 93 | +apple |
| 94 | +banana |
| 95 | +cherry |
| 96 | + |
| 97 | + |
| 98 | +tea coffee |
| 99 | +chocolate |
| 100 | +</span></code></pre> |
| 101 | +<p>And here's a surprising <code>GNU grep</code> solution, with a customizable group separator:</p> |
| 102 | +<pre style="background-color:#f5f5f5;"> |
| 103 | +<code><span style="color:#7f8989;"># single empty line |
| 104 | +</span><span style="color:#1f1f1f;">$ grep </span><span style="color:#72ab00;">--</span><span style="color:#1f1f1f;">group</span><span style="color:#72ab00;">-</span><span style="color:#1f1f1f;">separator= </span><span style="color:#72ab00;">-</span><span style="color:#5597d6;">A0 </span><span style="color:#d07711;">&#39;.&#39;</span><span style="color:#1f1f1f;"> ip.txt |
| 105 | +hello |
| 106 | + |
| 107 | +world |
| 108 | + |
| 109 | +apple |
| 110 | +banana |
| 111 | +cherry |
| 112 | + |
| 113 | +tea coffee |
| 114 | +chocolate |
| 115 | + |
| 116 | +</span><span style="color:#7f8989;"># double empty line |
| 117 | +# empty lines at the start/end of the input are removed too |
| 118 | +</span><span style="color:#1f1f1f;">$ </span><span style="color:#b39f04;">printf </span><span style="color:#d07711;">&#39;\n\n\ndragon\n\n\nunicorn\n\n\n&#39; </span><span style="color:#72ab00;">|</span><span style="color:#1f1f1f;"> grep </span><span style="color:#72ab00;">--</span><span style="color:#1f1f1f;">group</span><span style="color:#72ab00;">-</span><span style="color:#1f1f1f;">separator=</span><span style="color:#5597d6;">$&#39;</span><span style="color:#1f1f1f;">\n</span><span style="color:#d07711;">&#39; -A0 &#39;</span><span style="color:#1f1f1f;">.</span><span style="color:#d07711;">&#39; |
| 119 | +dragon |
| 120 | + |
| 121 | + |
| 122 | +unicorn |
| 123 | +</span></code></pre> |
| 124 | +<p><strong>Video demo</strong>:</p> |
| 125 | +<p align="center"><iframe width="560" height="315" loading="lazy" src="https://www.youtube.com/embed/DjNF2Sbwyxk" title="YouTube video player" frameborder="0" allow="accelerometer; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></p> |
| 126 | +<br> |
| 127 | +<p><img src="/images/info.svg" alt="info" /> See also my <a href="https://github.com/learnbyexample/cli_text_processing_coreutils">Command line text processing with GNU Coreutils</a>, <a href="https://github.com/learnbyexample/learn_gnuawk">GNU AWK</a> and <a href="https://github.com/learnbyexample/learn_gnugrep_ripgrep">GNU GREP and RIPGREP</a> ebooks.</p> |
| 128 | +</content> |
| 129 | + </entry> |
10 | 130 | <entry xml:lang="en">
|
11 | 131 | <title>Python tip 12: negate a regex grouping</title>
|
12 | 132 | <published>2022-06-22T00:00:00+00:00</published>
|
|
0 commit comments