24 - bash work with strings

Lecture



This is the last lecture dedicated to learning bash . Today we will talk about working with strings, as well as discuss bash commands and constructions that were missed in previous lectures. First, consider one of these important constructions, and then proceed to the processing of strings.

In many system scripts, you can see a post like this:

one
. / lib / lsb / init-functions

This is the point after which the space followed by the path to the file. Do not confuse this with the option without a space - ./lib/lsb/init-functions . A dot with a space after which follows the path to the text file allows you to load the text of this file into the current script. This mechanism can be compared with the *** *** include in the C language. This mechanism has a great practical application. For example, you can describe frequently used *** functions in a separate file, and then use functions in other scripts. The same mechanism is used to create configuration files. Consider a practical example. Create a file called testopt with the following content:

one
2
3
four
# Configuration file
# Set the display option:
PRINT = YES
PRINT2 = NO

Then create another script file named printopt.sh in the same directory as the testopt file:

one
2
3
four
#! / bin / bash
. testopt
if [$ PRINT = "YES"]; then echo "PRINT"; fi
if [$ PRINT2 = "YES"]; then echo "PRINT2"; fi

When the bash interpreter starts to parse the printopt.sh script at startup, thanks to the construction . The testopt executable file for the interpreter will look like this:

one
2
3
four
five
6
7
#! / bin / bash
# Configuration file
# Set the display option:
PRINT = YES
PRINT2 = NO
if [$ PRINT = "YES"]; then echo "PRINT"; fi
if [$ PRINT2 = "YES"]; then echo "PRINT2"; fi

That is, in place . testopt inserts the contents (text) of the testopt file. The result of the script:

one
2
igor @ ubuntu: ~ / linux $ ./printopt.sh
PRINT

Working with strings

Consider a few bash string processing techniques. Suppose there is a variable A , which is assigned the string “ QWERTY “. To display the contents of a variable, just write echo $ A :

one
2
igor @ ubuntu: ~ / linux $ A = "QWERTY"; echo $ A
Qwerty

Suppose we want to output such a string - QWERTASD . The $ AASD option does not work, since for bash - AASD will be a nonexistent variable:

one
igor @ ubuntu: ~ / linux $ A = "QWERTY"; echo $ AASD

Therefore, you should write as follows: $ {A} ASD :

one
2
igor @ ubuntu: ~ / linux $ A = "QWERTY"; echo $ {A} ASD
QWERTYASD

If it is necessary to display a string from the Nth character, then use the $ {A: N} construct, where N is the number of the character from which the string will be displayed. Characters in the line are numbered from scratch. To display ERTY we write:

one
2
igor @ ubuntu: ~ / linux $ A = "QWERTY"; echo $ {A: 2}
ERTY

In other words, after the colon, we indicate the number of characters to be skipped.

You can display a certain number of characters starting from a certain position. Then you need to write as $ {A: N: M} , where N is the number of the character from which the string will be displayed, and M is the number of displayed characters. To derive the ER characters from our QWERTY line, we write:

one
2
igor @ adm-ubuntu: ~ $ A = "QWERTY"; echo $ {A: 2: 2}
ER

To output QWE, we write this:

one
2
igor @ adm-ubuntu: ~ $ A = "QWERTY"; echo $ {A :: 3}
QWE

Consider this construction:

one
2
3
four
igor @ adm-ubuntu: ~ $ A = "ABABABCDCD"; echo $ {A # AB}
ABABCDCD
igor @ adm-ubuntu: ~ $ A = "123ABABABCDCD"; echo $ {A # AB}
123ABABABCDCD

After the # symbol, we specify a pattern, and if the beginning of the line matches this pattern, then the string will be output without characters that match the pattern. The line “123ABABABCDCD” starts from 12 and the AB template did not work, but if you write # * AB (or # ??? AB ), then we get the following result:

one
2
3
four
igor @ adm-ubuntu: ~ $ A = "123ABABABCDCD"; echo $ {A # * AB}
ABABCDCD
igor @ adm-ubuntu: ~ $ A = "123ABABABCDCD"; echo $ {A # ??? AB}
ABABCDCD

Look at the result of this command:

one
2
igor @ adm-ubuntu: ~ $ A = "123ABABABCDCD"; echo $ {A ## * AB}
CDCD

If we have one character #, then the minimum that satisfies the pattern is separated from the string. That is, for “123ABABABCDCD” is “123AB” . And if we have two ## signs, then the maximum possible part that satisfies the pattern is separated. That is, That is, for “123ABABABCDCD” is “123ABABAB” , since 123ABAB is suitable for * .

If it is necessary to remove characters from the end of the line in the same way, instead of # we use % . The rules are the same as for # .

one
2
3
four
igor @ adm-ubuntu: ~ $ A = "123ABABABCDCD"; echo $ {A% AB *}
123ABAB
igor @ adm-ubuntu: ~ $ A = "123ABABABCDCD"; echo $ {A %% AB *}
123

Now let's see how bash can replace characters in a string. Suppose you need in our line “123ABABABCDCD” to replace the characters AB with ZX , to make the line “123ZXZXZXCDCD” . For this we use / or // and write so:

one
2
3
four
igor @ adm-ubuntu: ~ $ A = "123ABABABCDCD"; echo $ {A / AB / ZX}
123ZXABABCDCD
igor @ adm-ubuntu: ~ $ A = "123ABABABCDCD"; echo $ {A // AB / ZX}
123ZXZXZXCDCD

Very often in scripts it is necessary to check whether a variable exists, and if it does not exist, create it and assign a specific value. The mechanism described below is used in scripts that read configuration files.

one
2
3
four
five
6
igor @ adm-ubuntu: ~ $ echo $ {options: = "YES"}
YES
igor @ adm-ubuntu: ~ $ echo $ options
YES
igor @ adm-ubuntu: ~ $ options = "NO"; echo $ {options: = "YES"}
NO

A com *** y $ {options: = ”YES”} should be understood like this: if the options variable does not exist, then you need to create it and set the value to “YES” , and if the options variable exists, then use its true value. In the command from the last example (line 1), the options variable did not exist, so it was created and assigned the value YES , in the next command (line 3), we see that the options variable was created and assigned the value.
In the following command (line 5), the options variable was created with the value NO (that is, it existed before the echo $ {options: = ”YES”} command) and therefore this value ( NO ) was displayed.

If you need to perform the same operation, but do not assign a value to a variable, then we write instead = , the symbol - :

one
2
3
four
igor @ adm-ubuntu: ~ $ echo $ {options1: - "YES"}
YES
igor @ adm-ubuntu: ~ $ echo $ options1
.

That is, if a variable does not exist, then it is not created, and the specified one is used instead of its nonexistent value (in the example, this is “YES” ). This construction works if the variable does not exist or it exists, but with a value of zero length.

If it is necessary, on the contrary, to output some value instead of an existing variable, then the following *** is used: a:

one
2
3
four
igor @ adm-ubuntu: ~ $ options = "NO"; echo $ {options: + "YES"}
YES
igor @ adm-ubuntu: ~ $ echo $ options
NO

That is, if a variable exists and a value of nonzero length is assigned to it, then output the specified value instead of the variable value, and do not change the variable itself.

Com *** and read

For some types of scripts (for example, installation scripts), it is necessary that the user enters any values ​​and they can be used further in the script. To solve this problem in bash there is a com *** and read . In the simplest case, a com *** is written like this: read P1 P2 .... PN , where P1 ... PN are the names of the parameters separated by spaces. A com *** and read reads data from the input stream and writes it into the specified variables. As a separator for the input data, the com *** and read uses the value that is stored in the bash system variable - IFS . Typically, this is a space or tab. Consider an example script:

one
2
3
four
five
#! / bin / bash
echo "Type your first and last name separated by a space and press Enter:"
read P1 P2
echo "Your name: $ P1"
echo "Your last name: $ P2"

And the result of the implementation:

one
2
3
four
five
igor @ adm-ubuntu: ~ / linux $ ./hello.sh
Type your first and last name separated by a space and press Enter:
Igor Kuzmenko
Your name: Igor
Your last name: Kuzmenko

If you change the 5th line of the script to echo “Your last name: $ {P2: -“ Last name was missing ”}” , then if you do not enter the last name, the specified value will be substituted:

one
2
3
four
five
igor @ adm-ubuntu: ~ / linux $ ./hello.sh
Type your first and last name separated by a space and press Enter:
Igor
Your name: Igor
Your last name: Last name was missing

Com *** and read can be executed with keys. The most significant are:

-n - allows you to specify the number of characters that must be read from the input stream;
-t - allows you to set the number of seconds to wait for data. If the user has not entered anything, after this time the com *** will be completed with an error and the script will be executed further.
-s - disables the display of input information on the console. Used to enter confidential information.

Help on the read command can be obtained from the console using the help read command.

This concludes our encounter with bash . I recommend viewing the scripts from the /etc/init.d/ directory, and now try to understand what each of them executes. So you better understand what happens when you start a service or its completion, and accordingly, when you start and end Linux itself . We certainly did not consider all the teams. I want to remind once again that bash can use both built-in commands and external ones. If you see an unfamiliar com *** u in scripts (take for example the same read ) and there is no help about it with the man read command, it’s probably built in bash com *** and you need to look either in man bash or use help read .

created: 2014-09-13
updated: 2021-03-13
132521



Rating 9 of 10. count vote: 2
Are you satisfied?:



Comments


To leave a comment
If you have any suggestion, idea, thanks or comment, feel free to write. We really value feedback and are glad to hear your opinion.
To reply

LINUX operating system

Terms: LINUX operating system