Sick Gaming
All about {Curly Braces} in Bash - Printable Version

+- Sick Gaming (https://www.sickgaming.net)
+-- Forum: Computers (https://www.sickgaming.net/forum-86.html)
+--- Forum: Linux, FreeBSD, and Unix types (https://www.sickgaming.net/forum-88.html)
+--- Thread: All about {Curly Braces} in Bash (/thread-89135.html)



All about {Curly Braces} in Bash - xSicKxBot - 03-08-2019

All about {Curly Braces} in Bash

<div style="margin: 5px 5% 10px 5%;"><img src="http://www.sickgaming.net/blog/wp-content/uploads/2019/02/all-about-curly-braces-in-bash.jpg" width="1700" height="847" title="" alt="" /></div><div><div><img src="http://www.sickgaming.net/blog/wp-content/uploads/2019/02/all-about-curly-braces-in-bash.jpg" class="ff-og-image-inserted" /></div>
<p>At this stage of our Bash basics series, it would be hard not to see some crossover between topics. For example, you have already seen a lot of brackets in the examples we have shown over the past several weeks, but the focus has been elsewhere.</p>
<p>For the next phase of the series, we’ll take a closer look at brackets, curly, curvy, or straight, how to use them, and what they do depending on where you use them. We will also tackle other ways of enclosing things, like when to use quotes, double-quotes, and backquotes.</p>
<p>This week, we’re looking at curly brackets or <i>braces</i>: <code>{}</code>.</p>
<h3>Array Builder</h3>
<p>You have already encountered curly brackets before in <a href="https://www.linux.com/blog/learn/2019/1/linux-tools-meaning-dot">The Meaning of Dot</a>. There, the focus was on the use of the dot/period (<code>.</code>), but using braces to build a sequence was equally important.</p>
<p>As we saw then:</p>
<pre> echo {0..10}
</pre>
<p>prints out the numbers from 0 to 10. Using:</p>
<pre> echo {10..0}
</pre>
<p>prints out the same numbers, but in reverse order. And,</p>
<pre> echo {10..0..2}
</pre>
<p>prints every second number, starting with 10 and making its way backwards to 0.</p>
<p>Then,</p>
<pre> echo {z..a..2}
</pre>
<p>prints every second letter, starting with <i>z</i> and working its way backwards until <i>a</i>.</p>
<p>And so on and so forth.</p>
<p>Another thing you can do is combine two or more sequences:</p>
<pre> echo {a..z}{a..z}
</pre>
<p>This prints out all the two letter combinations of the alphabet, from <i>aa</i> to <i>zz</i>.</p>
<p>Is this useful? Well, actually it is. You see, arrays in Bash are defined by putting elements between parenthesis <code>()</code> and separating each element using a space, like this:</p>
<pre> month=("Jan" "Feb" "Mar" "Apr" "May" "Jun" "Jul" "Aug" "Sep" "Oct" "Nov" "Dec")
</pre>
<p>To access an element within the array, you use its index within brackets <code>[]</code>:</p>
<pre> $ <b>echo ${month[3]}</b> # Array indexes start at [0], so [3] points to the fourth item Apr
</pre>
<p>You can accept all those brackets, parentheses, and braces on faith for a moment. We’ll talk about them presently.</p>
<p>Notice that, all things being equal, you can create an array with something like this:</p>
<pre> letter_combos=({a..z}{a..z})
</pre>
<p>and <code>letter_combos</code> points to an array that contains all the 2-letter combinations of the entire alphabet.</p>
<p>You can also do this:</p>
<pre> dec2bin=({0..1}{0..1}{0..1}{0..1}{0..1}{0..1}{0..1}{0..1}) </pre>
<p>This last one is particularly interesting because <code>dec2bin</code> now contains all the binary numbers for an 8-bit register, in ascending order, starting with 00000000, 00000001, 00000010, etc., until reaching 11111111. You can use this to build yourself an 8-bit decimal-to-binary converter. Say you want to know what 25 is in binary. You can do this:</p>
<pre> $ <b>echo ${dec2bin[25]}</b> 00011001
</pre>
<p>Yes, there are better ways of converting decimal to binary as we saw in <a href="https://www.linux.com/blog/learn/2019/2/logical-ampersand-bash">the article where we discussed &amp; as a logical operator</a>, but it is still interesting, right?</p>
<h3>Parameter expansion</h3>
<p>Getting back to</p>
<pre> echo ${month[3]}
</pre>
<p>Here the braces <code>{}</code> are not being used as apart of a sequence builder, but as a way of generating <i>parameter expansion</i>. Parameter expansion involves what it says on the box: it takes the variable or expression within the braces and expands it to whatever it represents.</p>
<p>In this case, <code>month</code> is the array we defined earlier, that is:</p>
<pre> month=("Jan" "Feb" "Mar" "Apr" "May" "Jun" "Jul" "Aug" "Sep" "Oct" "Nov" "Dec")
</pre>
<p>And, item 3 within the array points to <code>"Apr"</code> (remember: the first index in an array in Bash is <code>[0]</code>). That means that <code>echo ${month[3]}</code>, after the expansion, translates to <code>echo "Apr"</code>.</p>
<p>Interpreting a variable as its value is one way of expanding it, but there are a few more you can leverage. You can use parameter expansion to manipulate what you read from variable, say, by cutting a chunk off the end.</p>
<p>Suppose you have a variable like:</p>
<pre> a="Too longgg"
</pre>
<p>The command:</p>
<pre> echo ${a%gg}
</pre>
<p>chops off the last two gs and prints “<i>Too long</i>“.</p>
<p>Breaking this down,</p>
<ul>
<li><code>${...}</code> tells the shell to expand whatever is inside it</li>
<li><code>a</code> is the variable you are working with</li>
<li><code>%</code> tells the shell you want to chop something off the end of the expanded variable (“Too longgg”)</li>
<li>and <code>gg</code> is what you want to chop off.</li>
</ul>
<p>This can be useful for converting files from one format to another. Allow me to explain with a slight digression:</p>
<p><a href="http://www.imagemagick.org/">ImageMagick</a> is a set of command line tools that lets you manipulate and modify images. One of its most useful tools ImageMagick comes with is <code>convert</code>. In its simplest form <code>convert</code> allows you to, given an image in a certain format, make a copy of it in another format.</p>
<p>The following command takes a JPEG image called <i>image.jpg</i> and creates a PNG copy called <i>image.png</i>:</p>
<pre> convert image.jpg image.png
</pre>
<p>ImageMagick is often pre-installed on most Linux distros. If you can’t find it, look for it in your distro’s software manager.</p>
<p>Okay, end of digression. On to the example:</p>
<p>With variable expansion, you can do the same as shown above like this:</p>
<pre> i=image.jpg convert $i ${i%jpg}png
</pre>
<p>What you are doing here is chopping off the extension <code>jpg</code> from <code>i</code> and then adding <code>png</code>, making the command <code>convert image.jpg image.png</code>.</p>
<p>You may be wondering how this is more useful than just writing in the name of the file. Well, when you have a directory containing hundreds of JPEG images, you need to convert to PNG, run the following in it:</p>
<pre> for i in *.jpg; do convert $i ${i%jpg}png; done </pre>
<p>… and, hey presto! All the pictures get converted automatically.</p>
<p>If you need to chop off a chunk from the beginning of a variable, instead of <code>%</code>, use <code>#</code>:</p>
<pre> $ <b>a="Hello World!"</b> $ <b>echo Goodbye${a#Hello}</b> Goodbye World!
</pre>
<p>There’s quite a bit more to parameter expansion, but a lot of it makes sense only when you are writing scripts. We’ll explore more on that topic later in this series.</p>
<h3>Output Grouping</h3>
<p>Meanwhile, let’s finish up with something simple: you can also use <code>{ ... }</code> to group the output from several commands into one big blob. The command:</p>
<pre> echo "I found all these PNGs:"; find . -iname "*.png"; echo "Within this bunch of files:"; ls &gt; PNGs.txt
</pre>
<p>will execute all the commands but will only copy into the <i>PNGs.txt</i> file the output from the last <code>ls</code> command in the list. However, doing</p>
<pre> { echo "I found all these PNGs:"; find . -iname "*.png"; echo "Within this bunch of files:"; ls; } &gt; PNGs.txt
</pre>
<p>creates the file <i>PNGs.txt</i> with everything, starting with the line “<i>I found all these PNGs:</i>“, then the list of PNG files returned by <code>find</code>, then the line “Within this bunch of files:” and finishing up with the complete list of files and directories within the current directory.</p>
<p>Notice that there is space between the braces and the commands enclosed within them. That’s because <code>{</code> and <code>}</code> are <i>reserved words</i> here, commands built into the shell. They would roughly translate to “<i>group the outputs of all these commands together</i>” in plain English.</p>
<p>Also notice that the list of commands has to end with a semicolon (<code>;</code>) or the whole thing will bork.</p>
<h3>Next Time</h3>
<p>In our next installment, we’ll be looking at more things that enclose other things, but of different shapes. Until then, have fun!</p>
<p><em>Read more:</em></p>
<p><a href="https://www.linux.com/blog/learn/2019/2/and-ampersand-and-linux">And, Ampersand, and &amp; in Linux</a></p>
<p><a href="https://www.linux.com/blog/learn/2019/2/ampersands-and-file-descriptors-bash">Ampersands and File Descriptors in Bash</a></p>
<p><a href="https://www.linux.com/blog/learn/2019/2/logical-ampersand-bash">Logical &amp; in Bash</a></p>
</div>