πŸ“œ ⬆️ ⬇️

Bash scripts, part 3: command line options and keys

Bash scripts: start
Bash scripts, part 2: loops
Bash scripts, part 3: command line options and keys
Bash scripts, part 4: input and output
Bash Scripts, Part 5: Signals, Background Tasks, Script Management
Bash scripts, part 6: functions and library development
Bash scripts, part 7: sed and word processing
Bash scripts, part 8: awk data processing language
Bash scripts, part 9: regular expressions
Bash scripts, part 10: practical examples
Bash scripts, part 11: expect and automate interactive utilities

Having mastered the previous parts of this series of materials, you learned what bash scripts are, how to write them, how to manage the flow of program execution, how to work with files. Today we will talk about how to add interactivity to scripts, equipping them with opportunities for receiving data from the user and for processing this data.

image



The most common way to transfer data to scripts is to use command line parameters. Calling the script with the parameters, we give him some information with which it can work. It looks like this:
')
$ ./myscript 10 20 

In this example, the script passed two parameters - "10" and "20". All this is good, but how to read the data in the script?

Reading command line parameters


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


Here's how to use command line parameters in a script using these variables:

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

Run the script with the parameters:

 ./myscript 5 10 15 

This is what it will bring to the console.


Output of parameters with which the script is started

Note that the command line parameters are separated by spaces.

Take a look at another example of using parameters. Here we 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. 

Run the script and check the result of the calculation.


A script that finds the sum of the numbers passed to it.

Command line parameters do not have to be numbers. Scripts can also pass strings. For example, here's the script that works with the string:

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

Run it:

 ./myscript Adam 

He will bring what we expect from him.


Script working with string parameter

What if the parameter contains spaces, and we need to treat it as a separate data fragment? We believe 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 referring to them, the number in the variable name must be enclosed in curly brackets, for example:

 ${10} 

Parameter check


If the script is called without parameters, but for the normal operation of the code, their presence is assumed, an error will occur. Therefore, it is recommended to always check for the presence of parameters passed to the script during the call. For example, it can be organized like this:

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

Call the script first with a parameter, and then without parameters.


Calling the script that checks for the presence of command line parameters

Parameter counting


In the script, you can calculate 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 invoked.

Let's try it out:

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

Call the script.

 ./myscript 1 2 3 4 5 

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


Counting the number of parameters in the script

This variable provides an unusual way to get the last parameter passed to the script, not requiring knowledge of their number. Here's what it looks like:

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

Call the script and see what it displays.


Referring to the last parameter

Capture 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 $@ . Both contain all command line parameters, which makes it possible to access what is passed to the script, without using positional parameters.

The variable $* contains all parameters entered on the command line as a single β€œword”.

The variable $@ parameters are divided into separate "words". These parameters can be iterated in cycles.

Consider the difference between these variables in the examples. First, take a look at their contents:

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

Here is the output of the script.


Variables $ * and $ @

As you can see, the output of both variables is the same. Now we will try to go through the contents of these variables in cycles 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 brought to the console. The difference between the variables is quite obvious.


Parsing $ * and $ @ variables in a loop

The $* variable contains all parameters passed to the script as a single piece of data, while in the $@ 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 shift command in bash scripts with caution, since it literally shifts the values ​​of the positional parameters.

When you use this command, it defaults the values ​​of the positional parameters to the left. For example, the value of the variable $3 becomes the value of the variable $2 , the value of $2 becomes $1 , and what was before in $1, is lost. Note that the value of the $0 variable that contains the name of the script does not change.

Using the shift command, we will consider another way to iterate through 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 uses a while , checking the length of the value of the first parameter. When the length is equal to zero, the loop is exited. After checking the first parameter and displaying it on the screen, the shift command is called, which shifts the parameter values ​​by one position.


Using the shift command to iterate through parameters

Using the shift command, keep in mind that each time it is called, the value of the $1 variable is permanently lost.

Command line keys


Command line switches usually look like letters, before which a dash is placed. They are used 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 

Run the script:

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

And analyze what it will bring to the terminal.


Handling keys in the script

This code uses the case construction, which compares the key passed to it with the list of keys processed by the script. If the transferred value was in this list, the corresponding branch of the code is executed. If at the call of the script any key is used, the processing of which is not provided for, 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 keys. The standard way to do this is to use a special sequence of characters that tells the script when the keys end and the usual 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 end of the keys, what is left can be treated as parameters, and not as keys, without fear of errors. 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 break command to interrupt the while when it detects a double dash in the string.

That's what happens after you call it.


Handling keys and command line parameters

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

Handling keys with values


As your scripts become more complex, you will encounter situations where ordinary keys are no longer enough, which means you will need to use keys with certain values. For example, calling a script 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 with the command line keys:

 #!/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 

Call this script in this form:

 ./myscript -a -b test1 -d 

Let's look at the results of his work.


Handling key parameters

In this example, the case construction handles three keys. The -b switch requires an additional parameter. Since the key being processed is in the $1 variable, the corresponding parameter will be in $2 (the shift command is used here, therefore, as it is processed, everything that is passed to the script is shifted to the left). When we dealt with this, it remains only to extract the value of the $2 variable and we will have the parameter of the desired key. Of course, we need another shift command here so that the next key will fall into $1 .

Using standard keys


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

-a Display all objects.
-c Perform a count.
-d Specify the directory.
-e Expand the object.
-f Specify the file from which to read the data.
-h Print help on the command.
-i Ignore case.
-l Perform full-format output.
-n Use non-interactive (batch) mode.
-o Allows you to specify the file to which to redirect the output.
-q Run the script in quiet mode.
-r Process folders and files recursively.
-s Run the script in silent mode.
-v Run verbose output.
-x Exclude object.
-y Answer β€œyes” to all questions.

If you are running Linux, you most likely know many of these keys. By using them in the common meaning in your scripts, you will help users interact with them without worrying about reading the documentation.

Receive data from the user


The command line switches and parameters are a great way to get data from the person using the script, but in some cases more interactivity is needed.

Sometimes scripts need data that a user must enter during program execution. It is for this purpose that the bash shell contains the read command.

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

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

Notice that the echo command, which displays the prompt, is invoked with the -n key. This leads to the fact that at the end of the invitation does not display a newline character, which allows the script user to enter data in the same place where the invitation is located, and not on the next line.


Processing user input

When calling read you 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 display after launch.


Several variables in the read command

If, by calling read , you do not specify a variable, the data entered by the user will be placed in a special environment variable REPLY :

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


Using the REPLY environment variable

If the script should continue execution regardless of whether the user enters any data or not, by calling the read command, you can use the -t key. Namely, the key parameter sets the input wait time 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 the data is not entered within 5 seconds, the script will execute the branch of the conditional operator else , displaying an apology.


Time limit on data entry

Enter passwords


Sometimes what the user enters in response to a script question is better not to show on the screen. For example, this is usually done by requesting passwords. The -s key of the read command prevents the display of data entered from the keyboard. In fact, the data is output, but the read command makes 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.


Enter confidential data

Reading data from a file


The read command can, on every call, read one line of text from a file. When there are no more unread lines in the file, it will simply stop. If you need to get all the contents of the file in the script, you can use the pipeline to transfer the results of calling the cat for the file, the while construct that contains the read command (of course, using the cat looks primitive, but our goal is to show everything as simple as possible, newbies; experienced users sure will understand this).

Let's write a script that uses the approach just described for reading files.

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

Look at him in action.


Reading data from a file

Here we transferred to the while contents of the file and went through all the lines of this file, displaying the number and contents of each of them.

Results


Today we have analyzed the work with the keys and command line parameters. Without these tools, the use of scripts is extremely narrow. Even if the script is written, as they say, "for myself." Immediately we looked at 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 to the previous parts of this series of materials. If you have something to say about processing everything that can be transferred to the script at startup or during its operation, we are sure that many will be interested in reading about it.

Source: https://habr.com/ru/post/326328/


All Articles