avatarMikhail Raevskiy

Free AI web copilot to create summaries, insights and extended knowledge, download it at here

12146

Abstract

ram</span>"</span> count=(( <span class="hljs-variable">count</span> + <span class="hljs-number">1</span> )) <span class="hljs-keyword">done</span></pre></div><p id="1cbb">Take a look at what the script outputs to the console. The difference between the variables is pretty apparent.</p><div id="87b3"><pre>raevskym@DESKTOP<span class="hljs-literal">-JNF3L6H</span>:/bash_course<span class="hljs-variable"></span>./myscript <span class="hljs-number">1</span> <span class="hljs-number">2</span> <span class="hljs-number">3</span> <span class="hljs-number">4</span> <span class="hljs-number">5</span> <span class="hljs-variable"></span>* <span class="hljs-keyword">Parameter</span> <span class="hljs-comment">#1 = 1 2 3 4 5</span> <span class="hljs-variable"></span><span class="hljs-selector-tag">@</span> <span class="hljs-keyword">Parameter</span> <span class="hljs-comment">#1 = 1</span> <span class="hljs-variable"></span><span class="hljs-selector-tag">@</span> <span class="hljs-keyword">Parameter</span> <span class="hljs-comment">#2 = 2</span> <span class="hljs-variable"></span><span class="hljs-selector-tag">@</span> <span class="hljs-keyword">Parameter</span> <span class="hljs-comment">#3 = 3</span> <span class="hljs-variable"></span><span class="hljs-selector-tag">@</span> <span class="hljs-keyword">Parameter</span> <span class="hljs-comment">#4 = 4</span> <span class="hljs-variable"></span><span class="hljs-selector-tag">@</span> <span class="hljs-keyword">Parameter</span> <span class="hljs-comment">#5 = 5</span></pre></div><p id="98de">A variable<code>*</code>contains all parameters passed to the script as a single piece of data, while in a variable<code>@</code>they are represented by independent values. Which variable to use depends on what exactly is needed in a particular scenario.</p><h1 id="9203">Shift command</h1><p id="1c16">Use the command <code>shift</code>in bash scripts with caution, as it literally shifts the values ​​of positional parameters.</p><p id="604b">When you use this command, it shifts the positional parameter values ​​to the left by default. For example, the value of a variable <code>3</code>becomes the value of a variable <code>2</code>, the value <code>2</code>goes to <code>1</code>, and what was before that is <code>1, </code>lost. Note that this <code>0</code>does not change the value of the variable containing the script name.</p><p id="073d">Using the command <code>shift</code>, let's consider another way to iterate over the parameters passed to the script:</p><div id="a6ce"><pre><span class="hljs-meta">#!/bin/bash</span> count=1 <span class="hljs-keyword">while</span> [ -n <span class="hljs-string">"<span class="hljs-variable">1</span>"</span> ] <span class="hljs-keyword">do</span> <span class="hljs-built_in">echo</span> <span class="hljs-string">"Parameter #<span class="hljs-variable">count</span> = <span class="hljs-variable">1</span>"</span> count=(( <span class="hljs-variable">count</span> + <span class="hljs-number">1</span> )) <span class="hljs-built_in">shift</span> <span class="hljs-keyword">done</span></pre></div><p id="1796">The script runs a loop <code>while</code>, checking the length of the first parameter value. When the length becomes zero, the loop is exited. After checking the first parameter and displaying it on the screen, a command is called <code>shift</code>that shifts the parameter values ​​by one position.</p><div id="8fa3"><pre><span class="hljs-attribute">raevskym</span>@DESKTOP-JNF3L6H:/bash_course./myscript <span class="hljs-number">1</span> <span class="hljs-number">2</span> <span class="hljs-number">3</span> <span class="hljs-number">4</span> <span class="hljs-number">5</span> <span class="hljs-attribute">Parameter</span> #<span class="hljs-number">1</span> = <span class="hljs-number">1</span> <span class="hljs-attribute">Parameter</span> #<span class="hljs-number">2</span> = <span class="hljs-number">2</span> <span class="hljs-attribute">Parameter</span> #<span class="hljs-number">3</span> = <span class="hljs-number">3</span> <span class="hljs-attribute">Parameter</span> #<span class="hljs-number">4</span> = <span class="hljs-number">4</span> <span class="hljs-attribute">Parameter</span> #<span class="hljs-number">5</span> = <span class="hljs-number">5</span></pre></div><p id="02e6">When using the command<code>shift</code>, remember that each time it is called, the value of the variable is<code>1</code>irretrievably lost.</p><h1 id="c844">Command-line switches</h1><p id="15ce">Command-line switches usually look like letters preceded by a dash. They serve to manage scripts. Consider this example:</p><div id="1949"><pre><span class="hljs-meta">#!/bin/bash</span> <span class="hljs-built_in">echo</span> <span class="hljs-keyword">while</span> [ -n <span class="hljs-string">"<span class="hljs-variable">1</span>"</span> ] <span class="hljs-keyword">do</span> <span class="hljs-keyword">case</span> <span class="hljs-string">"<span class="hljs-variable">1</span>"</span> <span class="hljs-keyword">in</span> -a) <span class="hljs-built_in">echo</span> <span class="hljs-string">"Found the -a option"</span> ;; -b) <span class="hljs-built_in">echo</span> <span class="hljs-string">"Found the -b option"</span> ;; -c) <span class="hljs-built_in">echo</span> <span class="hljs-string">"Found the -c option"</span> ;; *) <span class="hljs-built_in">echo</span> <span class="hljs-string">"<span class="hljs-variable">1</span> is not an option"</span> ;; <span class="hljs-keyword">esac</span> <span class="hljs-built_in">shift</span> <span class="hljs-keyword">done</span></pre></div><p id="20c5">Let’s run the script:</p><div id="64a1"><pre><span class="hljs-meta prompt_"> </span><span class="language-bash">./myscript –a –b –c –d</span></pre></div><p id="646d">And let’s analyze what it displays in the terminal.</p><div id="2864"><pre>raevskym@DESKTOP-JNF3L6H:~/bash_course./myscript -a -b -c -d <span class="hljs-built_in">Found</span> the -a <span class="hljs-keyword">option</span> <span class="hljs-built_in">Found</span> the -b <span class="hljs-keyword">option</span> <span class="hljs-built_in">Found</span> the -c <span class="hljs-keyword">option</span> -d <span class="hljs-keyword">is</span> <span class="hljs-keyword">not</span> an <span class="hljs-keyword">option</span></pre></div><p id="4977">This code uses a construction<code>case</code>that checks the key passed to it against the list of keys handled by the script. If the passed value is found in this list, the corresponding branch is executed. If, when calling the script, any key is used, the processing of which is not provided, the <b>"*" </b>branch will be executed.</p><h1 id="2168">How to distinguish between keys and parameters</h1><p id="a8c1">Often, when writing bash scripts, a situation arises when you need to use both command line parameters and switches. The standard way to do this is to use a special character sequence that tells the script when keys end and normal parameters begin.</p><p id="93de">This sequence is a double dash (-). The shell uses it to indicate the position at which the list of keys ends. After the script detects the sign of the end of the keys, what is left can, without fear of errors, be processed as parameters, and not as keys. Let’s consider an example:</p><div id="552c"><pre><span class="hljs-meta">#!/bin/bash</span> <span class="hljs-keyword">while</span> [ -n <span class="hljs-string">"<span class="hljs-variable">1</span>"</span> ] <span class="hljs-keyword">do</span> <span class="hljs-keyword">case</span> <span class="hljs-string">"<span class="hljs-variable">1</span>"</span> <span class="hljs-keyword">in</span> -a) <span class="hljs-built_in">echo</span> <span class="hljs-string">"Found the -a option"</span> ;; -b) <span class="hljs-built_in">echo</span> <span class="hljs-string">"Found the -b option"</span>;; -c) <span class="hljs-built_in">echo</span> <span class="hljs-string">"Found the -c option"</span> ;; --) <span class="hljs-built_in">shift</span> <span class="hljs-built_in">break</span> ;; *) <span class="hljs-built_in">echo</span> <span class="hljs-string">"<span class="hljs-variable">1</span> is not an option"</span>;; <span class="hljs-keyword">esac</span> <span class="hljs-built_in">shift</span> <span class="hljs-keyword">done</span> count=1 <span class="hljs-keyword">for</span> param <span class="hljs-keyword">in</span> <span class="hljs-variable">@</span> <span class="hljs-keyword">do</span> <span class="hljs-built_in">echo</span> <span class="hljs-string">"Parameter #<span class="hljs-variable">count</span>: <span class="hljs-variable">param</span>"</span> count=(( <span class="hljs-variable">count</span> + <span class="hljs-number">1</span> )) <span class="hljs-keyword">done</span></pre></div><p id="9c82">This script uses the command <code>break</code>to interrupt the loop <code>while</code>when it encounters a double dash on a line.</p><p id="0ed3">Here’s what happens after calling it.</p><div id="02eb"><pre><span class="hljs-attribute">raevskym</span>@DESKTOP-JNF3L6H:~/bash_course./myscript -a -b -c -- <span class="hljs-number">5</span> <span class="hljs-number">10</span> <span class="hljs-number">15</span> <span class="hljs-attribute">Found</span> the -a option <span class="hljs-attribute">Found</span> the -b option <span class="hljs-attribute">Found</span> the -c option <span class="hljs-attribute">Parameter</span> #<span class="hljs-number">1</span>: <span class="hljs-number">5</span> <span class="hljs-attribute">Parameter</span> #<span class="hljs-number">2</span>: <span class="hljs-number">10</span> <span class="hljs-attribute">Parameter</span> #<span class="hljs-number">3</span>: <span class="hljs-number">15</span></pre></div><p id="1c0b">As you can see, when the script, parsing the data passed to it, finds a double dash, it finishes processing keys and considers everything that has not yet been processed as parameters.</p><h1 id="807f">Handling keys with values</h1><p id="102d">As your scripts become more complex, you will face situations where ordinary keys are no longer enough, which means that you will need to use keys with certain values. For example, a script call that uses this feature looks like this:</p><div id="8576"><pre>./myscript -<span class="hljs-selector-tag">a</span> test1 -<span class="hljs-selector-tag">b</span> -c test2</pre></div><p id="7e99">The script should be able to determine when additional parameters are used together with command-line switches:</p><div id="eb2a"><pre><span class="hljs-meta">#!/bin/bash</span> <span class="hljs-keyword">while</span> [ -n <span class="hljs-string">"<span class="hljs-variable">1</span>"</span> ] <span class="hljs-keyword">do</span> <span class="hljs-keyword">case</span> <span class="hljs-string">"<span class="hljs-variable">1</span>"</span> <span class="hljs-keyword">in</span> -a) <span class="hljs-built_in">echo</span> <span class="hljs-string">"Found the -a option"</span>;; -b) param=<span class="hljs-string">"<span class="hljs-variable">2</span>"</span> <span class="hljs-built_in">echo</span> <span class="hljs-string">"Found the -b option, with parameter value <span class="hljs-variable">param</span>"</span> <span class="hljs-built_in">shift</span> ;; -c) <span class="hljs-built_in">echo</span> <span class="hljs-string">"Found the -c option"</span>;; --) <span class="hljs-built_in">shift</span> <span class="hljs-built_in">break</span> ;; *) <span class="hljs-built_in">echo</span> <span class="hljs-string">"<span class="hljs-variable">1</span> is not an option"</span>;; <span class="hljs-keyword">esac</span> <span class="hljs-built_in">shift</span> <span class="hljs-keyword">done</span> count=1 <span class="hljs-keyword">for</span> param <span class="hljs-keyword">in</span> <span class="hljs-string">"<span class="hljs-variable">@</span>"</span> <span class="hljs-keyword">do</span> <span class="hljs-built_in">echo</span> <span class="hljs-string">"Parameter #<span class="hljs-variable">count</span>: <span class="hljs-variable">param</span>"</span> count=$((

Options

<span class="hljs-variable">count</span> + <span class="hljs-number">1</span> )) <span class="hljs-keyword">done</span></pre></div><p id="c881">Let’s call this script like this:</p><div id="7817"><pre>./myscript -<span class="hljs-selector-tag">a</span> -<span class="hljs-selector-tag">b</span> test1 -d</pre></div><p id="e1aa">Let’s look at the results of his work.</p><div id="ff89"><pre>raevskym@DESKTOP-JNF3L6H:~/bash_course./myscript -a -b <span class="hljs-number">15</span> -d <span class="hljs-built_in">Found</span> the -a <span class="hljs-keyword">option</span> <span class="hljs-built_in">Found</span> the -b <span class="hljs-keyword">option</span>, <span class="hljs-keyword">with</span> parameter <span class="hljs-keyword">value</span> <span class="hljs-number">15</span> <span class="hljs-built_in">Found</span> the -d <span class="hljs-keyword">option</span></pre></div><p id="9461">In this example, three keys are processed in the construct. The key<code>-b</code>requires an additional parameter. Since the key being processed is in a variable<code>1</code>, the corresponding parameter will be in<code>2</code>(the command is used here<code>shift</code>, therefore as processing proceeds, everything that is passed to the script is shifted to the left). When we figured it out, it remains only to extract the value of the variable<code>2, </code>and we will have the parameter of the required key. Of course, one more command is needed here<code>shift</code>in order for the next key to getting into<code>1</code>.</p><h1 id="1526">Using standard keys</h1><p id="f7c5">When writing bash scripts, you can choose any letters for command line keys and arbitrarily set the script’s reaction to these keys. However, in the Linux world, the values ​​of some keys have become something of a standard that is useful to adhere to. Here is a list of these keys:</p><blockquote id="b677"><p><code><i>-a</i></code><i>List all objects. <code>-c</code>Make a count. <code>-d</code>Specify directory. <code>-e</code>Expand the object. <code>-f</code>Specify the file from which to read data. <code>-h</code>Display command help. <code>-i</code>Ignore case. <code>-l</code>Perform full format data output. <code>-n</code>Use non-interactive (batch) mode. <code>-o</code>Allows you to specify the file to which you want to redirect the output. <code>-q</code>Execute the script in quiet mode. <code>-r</code>Process folders and files recursively. <code>-s</code>Execute the script in silent mode. <code>-v</code>Execute verbose output. <code>-x</code>Exclude object. <code>-y</code>Answer "yes" to all questions.</i></p></blockquote><p id="ab5d">If you are on Linux, you are likely familiar with many of these keys. By using them in their common sense in your scripts, you can help users interact with them without having to worry about reading the documentation.</p><h1 id="7625">Receiving data from the user</h1><p id="2ef5">Command-line switches and parameters are a great way to get data from the user of the script, but in some cases, more interactivity is needed.</p><p id="c888">Sometimes scripts need data that the user must enter during program execution. The bash shell has a command for this very purpose <code>read</code>.</p><p id="9ea3">This command allows you to accept input either from standard input (keyboard) or using other file descriptors. After receiving the data, this command puts it into a variable:</p><div id="97fa"><pre><span class="hljs-meta">#!/bin/bash</span> <span class="hljs-built_in">echo</span> -n <span class="hljs-string">"Enter your name: "</span> <span class="hljs-built_in">read</span> name <span class="hljs-built_in">echo</span> <span class="hljs-string">"Hello <span class="hljs-variable">name</span>, welcome to my program."</span></pre></div><p id="0902">Note that the command <code>echo</code>that displays the prompt is invoked with a switch <code>-n</code>. This results in no line feed being displayed at the end of the prompt, which allows the user of the script to enter data where the prompt appears rather than on the next line.</p><div id="7a96"><pre>raevskym<span class="hljs-variable">@DESKTOP</span>-<span class="hljs-variable constant_">JNF3L6H</span><span class="hljs-symbol">:~/bash_course</span><span class="hljs-variable">.</span>/myscript <span class="hljs-title class_">Enter</span> your <span class="hljs-symbol">name:</span> <span class="hljs-title class_">Adam</span> <span class="hljs-title class_">Hello</span> <span class="hljs-title class_">Adam</span>, welcome to my program.</pre></div><p id="9d8d">When calling,<code>read</code>you can specify several variables:</p><div id="9da6"><pre><span class="hljs-meta">#!/bin/bash</span> <span class="hljs-built_in">read</span> -p <span class="hljs-string">"Enter your name: "</span> first last <span class="hljs-built_in">echo</span> <span class="hljs-string">"Your data for <span class="hljs-variable">last</span>, <span class="hljs-variable">first</span>..."</span></pre></div><p id="da89">This is what the script will output after running.</p><div id="cdc9"><pre>raevskym<span class="hljs-variable">@DESKTOP</span>-<span class="hljs-variable constant_">JNF3L6H</span><span class="hljs-symbol">:/bash_course</span><span class="hljs-variable">.</span>/myscript <span class="hljs-title class_">Enter</span> you <span class="hljs-symbol">name:</span> first last <span class="hljs-title class_">Your</span> data <span class="hljs-keyword">for</span> last, first...</pre></div><p id="0d9c">If, by calling<code>read</code>, do not specify a variable, the data entered by the user will be placed in a special environment variable<code>REPLY</code>:</p><div id="a084"><pre><span class="hljs-meta">#!/bin/bash</span> <span class="hljs-built_in">read</span> -p <span class="hljs-string">"Enter your name: "</span> <span class="hljs-built_in">echo</span> Hello <span class="hljs-variable">REPLY</span>, welcome to my program.</pre></div><p id="268e">This will produce the following behavior:</p><div id="c4bc"><pre>raevskym<span class="hljs-variable">@DESKTOP</span>-<span class="hljs-variable constant_">JNF3L6H</span><span class="hljs-symbol">:/bash_course</span><span class="hljs-variable">.</span>/myscript <span class="hljs-title class_">Enter</span> your <span class="hljs-symbol">name:</span> <span class="hljs-title class_">Adam</span> <span class="hljs-title class_">Hello</span> <span class="hljs-title class_">Adam</span>, welcome to my program.</pre></div><p id="1093">If the script should continue execution regardless of whether the user enters some data or not,<code>read</code>you can use the key when invoking the command<code>-t</code>. Namely, the key parameter sets the waiting time for input in seconds:</p><div id="7464"><pre><span class="hljs-meta">#!/bin/bash</span> <span class="hljs-keyword">if</span> <span class="hljs-built_in">read</span> -t 5 -p <span class="hljs-string">"Enter your name: "</span> name <span class="hljs-keyword">then</span> <span class="hljs-built_in">echo</span> <span class="hljs-string">"Hello <span class="hljs-variable">name</span>, welcome to my script"</span> <span class="hljs-keyword">else</span> <span class="hljs-built_in">echo</span> <span class="hljs-string">"Sorry, too slow!"</span> <span class="hljs-keyword">fi</span></pre></div><p id="fa18">If no data is entered within 5 seconds, the script will execute the conditional statement branch <code>else</code>, outputting an apology.</p><div id="323b"><pre>raevskym<span class="hljs-variable">@DESKTOP</span>-<span class="hljs-variable constant_">JNF3L6H</span><span class="hljs-symbol">:/bash_course</span><span class="hljs-variable">.</span>/myscript <span class="hljs-title class_">Enter</span> your <span class="hljs-symbol">name:</span> <span class="hljs-title class_">Sorry</span>, to slow!</pre></div><h1 id="9cbf">Entering passwords</h1><p id="f09c">Sometimes it is better not to show what the user enters in response to the script question. For example, this is usually done when asking for passwords. The <code>-s </code>command key <code>read</code>prevents keyboard input from being displayed on the screen. In fact, the data is output, but the command <code>read</code>makes the text color the same as the background color.</p><div id="a083"><pre><span class="hljs-meta">#!/bin/bash</span> <span class="hljs-built_in">read</span> -s -p <span class="hljs-string">"Enter your password: "</span> pass <span class="hljs-built_in">echo</span> <span class="hljs-string">"Is your password really <span class="hljs-variable">pass</span>? "</span></pre></div><p id="ba22">This is how this script will work.</p><div id="5116"><pre>raevskym<span class="hljs-variable">@DESKTOP</span>-<span class="hljs-variable constant_">JNF3L6H</span><span class="hljs-symbol">:/bash_course</span><span class="hljs-variable">.</span>/myscript <span class="hljs-title class_">Enter</span> your <span class="hljs-symbol">password:</span> <span class="hljs-title class_">Is</span> you password really secretpass?</pre></div><h1 id="cb8f">Reading data from a file</h1><p id="fa98">The command <code>read</code>can, on each call, read one line of text from the file. When there are no more unread lines in the file, it will simply stop. If you need to get the entire contents of a file in a script, you can, using a pipeline, transfer the results of calling a command <code>cat</code>for a file, a structure <code>while</code>that contains a command <code>read </code>(of course, using the command <code>cat</code>looks primitive, but our goal is to show everything as simply as possible, focusing on beginners; experienced users, we are sure they will understand it).</p><p id="e759">Let’s write a script that uses the approach to reading files just described.</p><div id="3b5d"><pre><span class="hljs-meta">#!/bin/bash</span> count=1 <span class="hljs-built_in">cat</span> myfile | <span class="hljs-keyword">while</span> <span class="hljs-built_in">read</span> line <span class="hljs-keyword">do</span> <span class="hljs-built_in">echo</span> <span class="hljs-string">"Line <span class="hljs-variable">count</span>: <span class="hljs-variable">line</span>"</span> count=(( <span class="hljs-variable">count</span> + <span class="hljs-number">1</span> )) <span class="hljs-keyword">done</span> <span class="hljs-built_in">echo</span> <span class="hljs-string">"Finished"</span></pre></div><p id="2699">Let’s look at it in action.</p><div id="af3d"><pre>raevskym<span class="hljs-variable">@DESKTOP</span>-<span class="hljs-variable constant_">JNF3L6H</span><span class="hljs-symbol">:~/bash_course</span><span class="hljs-variable">.</span>/myscript <span class="hljs-title class_">Line</span> <span class="hljs-number">1</span>: hello <span class="hljs-title class_">Line</span> <span class="hljs-number">2</span>: this <span class="hljs-title class_">Line</span> <span class="hljs-number">3</span>: is <span class="hljs-title class_">Line</span> <span class="hljs-number">4</span>: test <span class="hljs-title class_">Finished</span></pre></div><p id="18f7">Here we passed the<code>while</code>contents of the file into a loop and went through all the lines of this file, displaying the number and contents of each of them.</p><h1 id="3f8b">Outcome</h1><p id="40a9">Today we have examined working with switches and command line parameters. Without these tools, the scope for scripting is extremely narrow. Even if the script is written, as they say, “for me.” Here we examined the approaches to receiving data from the user during program execution — this makes the scripts interactive.</p><p id="15f6">Next time, let’s talk about input and output operations.</p><p id="3719">Dear Readers! Thank you for sharing your experience in the comments on the previous parts of this series. If you have something to say about the processing of everything that can be passed to the script at startup or while it is running, we are sure that many will be interested in reading about it.</p><p id="19a5">Source: <a href="https://habr.com/ru/company/ruvds/">https://habr.com/ru/company/ruvds/</a></p></article></body>

Bash Scripts — Part 3 — Command-Line Options and Switches

Having mastered the previous parts of this series, you learned about what bash scripts are, how to write them, how to control the flow of a program, how to work with files. Today we will talk about how to add interactivity to scripts, equipping them with capabilities to receive data from the user and to process this data.

Photo by Fernando Hernandez on Unsplash

The most common way to pass data to scripts is by using command line parameters. By calling the script with parameters, we give it some information with which it can work. It looks like this:

$ ./myscript 10 20

In this example, the script is passed with two arguments — “10” and “20”. All this is good, but how do you read the data in the script?

Reading command line parameters

The bash shell assigns command line parameters entered when invoking the script to special variables called positional parameters:

  • $0- the name of the script.
  • $1- first parameter.
  • $2- the second parameter - and so on, up to the variable $9 that contains the ninth parameter.

Here’s how you can use command line parameters in a script using these variables:

#!/bin/bash
echo $0
echo $1
echo $2
echo $3

Let’s run the script with parameters:

./myscript 5 10 15

This is what it will output to the console:

raevskym@DESKTOP-JNF3L6H:~/bash_course$./myscript 5 10 15
./myscript
5
10
15

Please note that command line parameters are separated by spaces.

Let’s take a look at another example of using parameters. Here we will find the sum of the numbers passed to the script:

#!/bin/bash
total=$[ $1 + $2 ]
echo "The first parameter is $1."
echo "The second parameter is $2."
echo "The sum is $total."

Let’s run the script and check the calculation result.

raevskym@DESKTOP-JNF3L6H:~/bash_course$./myscript 5 10
The first parameter is 5.
The second parameter is 10.
The sum is 15.

Command-line parameters do not have to be numbers. You can also pass strings to scripts. For example, here’s a script that works with a string:

#!/bin/bash
echo "Hello $1, how do you do"

Let’s run it:

./myscript Adam

He will output what we expect from him:

raevskym@DESKTOP-JNF3L6H:~/bash_course$./myscript Adam
Hello Adam, how do you do

What if the parameter contains spaces, and we need to process it as an independent piece of data? We assume that if you have mastered the previous parts of this guide, you already know the answer. It consists in the use of quotes.

If the script needs more than nine parameters when accessing them, the number in the variable name must be enclosed in curly braces, for example:

${10}

Parameter check

If the script is called without parameters, but the code is supposed to have them for normal operation, an error will occur. Therefore, it is recommended to always check for the presence of parameters passed to the script when invoked. For example, it can be organized like this:

#!/bin/bash
if [ -n "$1" ]
then
echo "Hello $1."
else
echo "No parameters found."
fi

Let’s call the script first with a parameter, and then without parameters.

raevskym@DESKTOP-JNF3L6H:~/bash_course$./myscript Adam
Hello Adam.
raevskym@DESKTOP-JNF3L6H:~/bash_course$./myscript
No paremeters found.

Counting parameters

In the script, you can count the number of parameters passed to it. The bash shell provides a special variable for this. Namely, the variable $#contains the number of parameters passed to the script when called.

Let’s try it out:

#!/bin/bash
echo "There were $# parameters passed."

Let’s call the script.

./myscript 1 2 3 4 5

As a result, the script will report that five parameters have been passed to it.

raevskym@DESKTOP-JNF3L6H:~/bash_course$./myscript 1 2 3 4 5
There were 5 parameters passed.

This variable provides an unusual way to get the last of the parameters passed to the script, which does not require knowing their number. This is how it looks:

#!/bin/bash
echo "The last parameter was ${!#}"

Let’s call the script and see what it outputs:

raevskym@DESKTOP-JNF3L6H:~/bash_course$./myscript 1 2 3 4 5
The last parameter was 5

Capturing all command-line options

In some cases, you need to capture all the parameters passed to the script. To do this, you can use the variables $*and $@. They both contain all the command line parameters, making it possible to access what is passed to the script without using positional parameters.

The variable $*contains all the parameters entered on the command line in the form of a single "word."

In the variable, the $@parameters are split into separate "words." These parameters can be iterated over in loops.

Let’s see the difference between these variables with examples. Let’s take a look at their contents first:

#!/bin/bash
echo "Using the \$* method: $*"
echo "-----------"
echo "Using the \$@ method: $@"

Here is the script output:

raevskym@DESKTOP-JNF3L6H:~/bash_course$./myscript 1 2 3 4 5
Using the \$* method: 1 2 3 4 5
-----------
Using the \$@ method: 1 2 3 4 5

As you can see, the output of both variables is the same. Now let’s try to go through the contents of these variables in loops in order to see the difference between them:

#!/bin/bash
count=1
for param in "$*"
do
echo "\$* Parameter #$count = $param"
count=$(( $count + 1 ))
done
count=1
for param in "$@"
do
echo "\$@ Parameter #$count = $param"
count=$(( $count + 1 ))
done

Take a look at what the script outputs to the console. The difference between the variables is pretty apparent.

raevskym@DESKTOP-JNF3L6H:~/bash_course$./myscript 1 2 3 4 5
$* Parameter #1 = 1 2 3 4 5
$@ Parameter #1 = 1
$@ Parameter #2 = 2
$@ Parameter #3 = 3
$@ Parameter #4 = 4
$@ Parameter #5 = 5

A variable$*contains all parameters passed to the script as a single piece of data, while in a variable$@they are represented by independent values. Which variable to use depends on what exactly is needed in a particular scenario.

Shift command

Use the command shiftin bash scripts with caution, as it literally shifts the values ​​of positional parameters.

When you use this command, it shifts the positional parameter values ​​to the left by default. For example, the value of a variable $3becomes the value of a variable $2, the value $2goes to $1, and what was before that is $1, lost. Note that this $0does not change the value of the variable containing the script name.

Using the command shift, let's consider another way to iterate over the parameters passed to the script:

#!/bin/bash
count=1
while [ -n "$1" ]
do
echo "Parameter #$count = $1"
count=$(( $count + 1 ))
shift
done

The script runs a loop while, checking the length of the first parameter value. When the length becomes zero, the loop is exited. After checking the first parameter and displaying it on the screen, a command is called shiftthat shifts the parameter values ​​by one position.

raevskym@DESKTOP-JNF3L6H:~/bash_course$./myscript 1 2 3 4 5
Parameter #1 = 1
Parameter #2 = 2
Parameter #3 = 3
Parameter #4 = 4
Parameter #5 = 5

When using the commandshift, remember that each time it is called, the value of the variable is$1irretrievably lost.

Command-line switches

Command-line switches usually look like letters preceded by a dash. They serve to manage scripts. Consider this example:

#!/bin/bash
echo
while [ -n "$1" ]
do
case "$1" in
-a) echo "Found the -a option" ;;
-b) echo "Found the -b option" ;;
-c) echo "Found the -c option" ;;
*) echo "$1 is not an option" ;;
esac
shift
done

Let’s run the script:

$ ./myscript –a –b –c –d

And let’s analyze what it displays in the terminal.

raevskym@DESKTOP-JNF3L6H:~/bash_course$./myscript -a -b -c -d
Found the -a option
Found the -b option
Found the -c option
-d is not an option

This code uses a constructioncasethat checks the key passed to it against the list of keys handled by the script. If the passed value is found in this list, the corresponding branch is executed. If, when calling the script, any key is used, the processing of which is not provided, the "*" branch will be executed.

How to distinguish between keys and parameters

Often, when writing bash scripts, a situation arises when you need to use both command line parameters and switches. The standard way to do this is to use a special character sequence that tells the script when keys end and normal parameters begin.

This sequence is a double dash (-). The shell uses it to indicate the position at which the list of keys ends. After the script detects the sign of the end of the keys, what is left can, without fear of errors, be processed as parameters, and not as keys. Let’s consider an example:

#!/bin/bash
while [ -n "$1" ]
do
case "$1" in
-a) echo "Found the -a option" ;;
-b) echo "Found the -b option";;
-c) echo "Found the -c option" ;;
--) shift
break ;;
*) echo "$1 is not an option";;
esac
shift
done
count=1
for param in $@
do
echo "Parameter #$count: $param"
count=$(( $count + 1 ))
done

This script uses the command breakto interrupt the loop whilewhen it encounters a double dash on a line.

Here’s what happens after calling it.

raevskym@DESKTOP-JNF3L6H:~/bash_course$./myscript -a -b -c -- 5 10 15
Found the -a option
Found the -b option
Found the -c option
Parameter #1: 5
Parameter #2: 10
Parameter #3: 15

As you can see, when the script, parsing the data passed to it, finds a double dash, it finishes processing keys and considers everything that has not yet been processed as parameters.

Handling keys with values

As your scripts become more complex, you will face situations where ordinary keys are no longer enough, which means that you will need to use keys with certain values. For example, a script call that uses this feature looks like this:

./myscript -a test1 -b -c test2

The script should be able to determine when additional parameters are used together with command-line switches:

#!/bin/bash
while [ -n "$1" ]
do
case "$1" in
-a) echo "Found the -a option";;
-b) param="$2"
echo "Found the -b option, with parameter value $param"
shift ;;
-c) echo "Found the -c option";;
--) shift
break ;;
*) echo "$1 is not an option";;
esac
shift
done
count=1
for param in "$@"
do
echo "Parameter #$count: $param"
count=$(( $count + 1 ))
done

Let’s call this script like this:

./myscript -a -b test1 -d

Let’s look at the results of his work.

raevskym@DESKTOP-JNF3L6H:~/bash_course$./myscript -a -b 15 -d
Found the -a option
Found the -b option, with parameter value 15
Found the -d option

In this example, three keys are processed in the construct. The key-brequires an additional parameter. Since the key being processed is in a variable$1, the corresponding parameter will be in$2(the command is used hereshift, therefore as processing proceeds, everything that is passed to the script is shifted to the left). When we figured it out, it remains only to extract the value of the variable$2, and we will have the parameter of the required key. Of course, one more command is needed hereshiftin order for the next key to getting into$1.

Using standard keys

When writing bash scripts, you can choose any letters for command line keys and arbitrarily set the script’s reaction to these keys. However, in the Linux world, the values ​​of some keys have become something of a standard that is useful to adhere to. Here is a list of these keys:

-aList all objects. -cMake a count. -dSpecify directory. -eExpand the object. -fSpecify the file from which to read data. -hDisplay command help. -iIgnore case. -lPerform full format data output. -nUse non-interactive (batch) mode. -oAllows you to specify the file to which you want to redirect the output. -qExecute the script in quiet mode. -rProcess folders and files recursively. -sExecute the script in silent mode. -vExecute verbose output. -xExclude object. -yAnswer "yes" to all questions.

If you are on Linux, you are likely familiar with many of these keys. By using them in their common sense in your scripts, you can help users interact with them without having to worry about reading the documentation.

Receiving data from the user

Command-line switches and parameters are a great way to get data from the user of the script, but in some cases, more interactivity is needed.

Sometimes scripts need data that the user must enter during program execution. The bash shell has a command for this very purpose read.

This command allows you to accept input either from standard input (keyboard) or using other file descriptors. After receiving the data, this command puts it into a variable:

#!/bin/bash
echo -n "Enter your name: "
read name
echo "Hello $name, welcome to my program."

Note that the command echothat displays the prompt is invoked with a switch -n. This results in no line feed being displayed at the end of the prompt, which allows the user of the script to enter data where the prompt appears rather than on the next line.

raevskym@DESKTOP-JNF3L6H:~/bash_course$./myscript
Enter your name: Adam
Hello Adam, welcome to my program.

When calling,readyou can specify several variables:

#!/bin/bash
read -p "Enter your name: " first last
echo "Your data for $last, $first..."

This is what the script will output after running.

raevskym@DESKTOP-JNF3L6H:~/bash_course$./myscript
Enter you name: first last
Your data for last, first...

If, by callingread, do not specify a variable, the data entered by the user will be placed in a special environment variableREPLY:

#!/bin/bash
read -p "Enter your name: "
echo Hello $REPLY, welcome to my program.

This will produce the following behavior:

raevskym@DESKTOP-JNF3L6H:~/bash_course$./myscript
Enter your name: Adam
Hello Adam, welcome to my program.

If the script should continue execution regardless of whether the user enters some data or not,readyou can use the key when invoking the command-t. Namely, the key parameter sets the waiting time for input in seconds:

#!/bin/bash
if read -t 5 -p "Enter your name: " name
then
echo "Hello $name, welcome to my script"
else
echo "Sorry, too slow!"
fi

If no data is entered within 5 seconds, the script will execute the conditional statement branch else, outputting an apology.

raevskym@DESKTOP-JNF3L6H:~/bash_course$./myscript
Enter your name: Sorry, to slow!

Entering passwords

Sometimes it is better not to show what the user enters in response to the script question. For example, this is usually done when asking for passwords. The -s command key readprevents keyboard input from being displayed on the screen. In fact, the data is output, but the command readmakes the text color the same as the background color.

#!/bin/bash
read -s -p "Enter your password: " pass
echo "Is your password really $pass? "

This is how this script will work.

raevskym@DESKTOP-JNF3L6H:~/bash_course$./myscript
Enter your password: Is you password really secretpass?

Reading data from a file

The command readcan, on each call, read one line of text from the file. When there are no more unread lines in the file, it will simply stop. If you need to get the entire contents of a file in a script, you can, using a pipeline, transfer the results of calling a command catfor a file, a structure whilethat contains a command read (of course, using the command catlooks primitive, but our goal is to show everything as simply as possible, focusing on beginners; experienced users, we are sure they will understand it).

Let’s write a script that uses the approach to reading files just described.

#!/bin/bash
count=1
cat myfile | while read line
do
echo "Line $count: $line"
count=$(( $count + 1 ))
done
echo "Finished"

Let’s look at it in action.

raevskym@DESKTOP-JNF3L6H:~/bash_course$./myscript
Line 1: hello
Line 2: this
Line 3: is
Line 4: test
Finished

Here we passed thewhilecontents of the file into a loop and went through all the lines of this file, displaying the number and contents of each of them.

Outcome

Today we have examined working with switches and command line parameters. Without these tools, the scope for scripting is extremely narrow. Even if the script is written, as they say, “for me.” Here we examined the approaches to receiving data from the user during program execution — this makes the scripts interactive.

Next time, let’s talk about input and output operations.

Dear Readers! Thank you for sharing your experience in the comments on the previous parts of this series. If you have something to say about the processing of everything that can be passed to the script at startup or while it is running, we are sure that many will be interested in reading about it.

Source: https://habr.com/ru/company/ruvds/

Linux
Command Line
Bash
Programming
Coding
Recommended from ReadMedium