Chapter 6 Advanced Shell script programming

Posted by webAmeteur on Thu, 11 Nov 2021 05:36:57 +0100

7.9 examples

Example: generate 10 random numbers, save them in the array, and find their maximum and minimum values

[root@rocky8 ~]# vim max_min.sh
#!/bin/bash
#
#**********************************************************************************************
#Author:        Raymond
#QQ:            88563128
#Date:          2021-10-22
#FileName:      max_min.sh
#URL:           raymond.blog.csdn.net
#Description:   The test script
#Copyright (C): 2021 All rights reserved
#*********************************************************************************************
declare -i min max
declare -a nums
for ((i=0;i<10;i++));do
    nums[$i]=$RANDOM
    [ $i -eq 0 ] && min=${nums[0]} && max=${nums[0]} && continue                                                                 
    [ ${nums[$i]} -gt $max ] && max=${nums[$i]} && continue
    [ ${nums[$i]} -lt $min ] && min=${nums[$i]}
done
echo "All numbers are ${nums[*]}"
echo Max is $max
echo Min is $min

[root@rocky8 ~]# bash max_min.sh
All numbers are 11268 31340 1794 24730 32582 4141 21637 25521 22265 12240
Max is 32582
Min is 1794

Example: write a script to define an array. The corresponding values of the elements in the array are all files ending in. Log under the / var/log directory; Count the sum of lines in the file with even subscript

[root@rocky8 ~]# vim array.sh
#!/bin/bash
#
#**********************************************************************************************
#Author:        Raymond
#QQ:            88563128
#Date:          2021-10-22
#FileName:      array.sh
#URL:           raymond.blog.csdn.net
#Description:   The test script
#Copyright (C): 2021 All rights reserved
#*********************************************************************************************
declare -a files
files=(/var/log/*.log)
declare -i lines=0
for i in $(seq 0 $[${#files[*]}-1]); do
    if [ $[$i%2] -eq 0 ];then
        let lines+=$(wc -l ${files[$i]} | cut -d' ' -f1)
    fi
done
echo "Lines: $lines"

[root@rocky8 ~]# bash array.sh 
Lines: 1311

7.10 practice

  1. Input several values into the array, and use the bubbling algorithm to sort in ascending or descending order
  2. Implement transpose matrix.sh as shown in the following figure
    1 2 3 1 4 7
    4 5 6 ===> 2 5 8
    7 8 9 3 6 9
  3. Print Yang Hui triangle

8. String processing

8.1 string slicing

Get string based on offset

#Returns the length of the string variable var, and a Chinese character is also counted as one
${#var}

#Return string variable var Zhongcong No offset After characters (excluding the second character) offset (characters) to the last part, offset The value of is between 0 and ${#var}-1 (negative value is allowed after bash 4.2)
${var:offset}

#Returns the part of the string variable var with a length of number starting from the character after the offset character (excluding the offset character)
${var:offset:number}

#Take the rightmost characters of the string and the rightmost characters of the string. Note: there must be a blank character after the colon
${var: -length}

#Skip the offset character from the leftmost side and take the content before lengh characters from the rightmost side to the right, that is, stop at the beginning and end
${var:offset:-length}

#First take length characters from the rightmost to the left, and then take the content between offset characters from the rightmost to the right. Note: there is a space before - length, and the length must be greater than offset
${var: -length:-offset}

example:

[root@rocky8 ~]# alpha=`echo {a..z}|tr -d ' '`
[root@rocky8 ~]# echo $alpha
abcdefghijklmnopqrstuvwxyz
[root@rocky8 ~]# echo ${#alpha}
26
[root@rocky8 ~]# echo ${alpha:10} #Skip the first 10
klmnopqrstuvwxyz

[root@rocky8 ~]# echo ${alpha:10:6} #Skip the first 10 and take 6
klmnop

[root@rocky8 ~]# echo ${alpha:-6}
abcdefghijklmnopqrstuvwxyz #-6 it doesn't work without a space in front
[root@rocky8 ~]# echo ${alpha: -6} #Countdown 6
uvwxyz

[root@rocky8 ~]# echo ${alpha: -6:3} #Top 3 of the last 6
uvw

[root@rocky8 ~]# echo ${alpha:6:-5} #break off both ends
ghijklmnopqrstu

[root@rocky8 ~]# echo ${alpha: -6:-5} #Count down 6, skip the count down 5
u

Pattern based substring

#Word can be any character specified. From left to right, find the word that appears for the first time in the string stored by var variable, delete all characters from the beginning of the string to the first occurrence of word string (including), that is, lazy mode, and delete the left and leave the right with the first word as the boundary
${var#*word}: 

#The same as above, greedy mode. The difference is that it deletes all the contents from the beginning of the string to the last character specified by word, that is, greedy mode. It deletes the left and leaves the right bounded by the last word
${var##*word}: 

example:

[root@rocky8 ~]# file="var/log/messages"
[root@rocky8 ~]# echo ${file#*/}
log/messages
[root@rocky8 ~]# echo ${file##*/}
messages

[root@rocky8 ~]# url=http://www.raymond.com/index.html
[root@rocky8 ~]# echo ${url#*/}
/www.raymond.com/index.html
[root@rocky8 ~]# echo ${url##*/}
index.html
#Word can be any character specified. Function: from right to left, find the word that appears for the first time in the string stored by var variable, delete all characters from the last character of the string to the left (forward) to the word string (including) that appears for the first time, that is, lazy mode, and delete the right and leave the left with the first word from right to left as the boundary
${var%word*}

#The same as above, but delete all characters between the rightmost character of the string and the last word character, that is, greedy mode. Delete the right and leave the left with the last word from right to left as the boundary
${var%%word*}

example:

[root@rocky8 ~]# echo ${file%/*}
var/log
[root@rocky8 ~]# echo ${file%%/*}
var
[root@rocky8 ~]# echo ${url%%/*}
http:

[root@rocky8 ~]# url=http://www.raymond.com:8080
[root@rocky8 ~]# echo ${url%%:*}
http
[root@rocky8 ~]# echo ${url##*:}
8080

8.2 finding and replacing

#Find the string represented by var that is matched by pattern for the first time, and replace it with substr
${var/pattern/substr}

#Find all strings that can be matched by pattern in the string represented by var and replace them with substr
${var//pattern/substr}

#Find the string represented by var whose first line is matched by pattern, and replace it with substr
${var/#pattern/substr}

#Find the string whose end of the line is matched by pattern in the string represented by var, and replace it with substr
${var/%pattern/substr}

example:

[root@rocky8 ~]# echo ${url/:/+/}
http+///www.raymond.com:8080
[root@rocky8 ~]# echo ${url//:/+/}
http+///www.raymond.com+/8080

[root@rocky8 ~]# getent passwd root
root:x:0:0:root:/root:/bin/bash
[root@rocky8 ~]# line=`getent passwd root`
[root@rocky8 ~]# echo $line
root:x:0:0:root:/root:/bin/bash
[root@rocky8 ~]# echo ${line/#root/admin/}
admin/:x:0:0:root:/root:/bin/bash

[root@rocky8 ~]# line1=1:`getent passwd root`
[root@rocky8 ~]# echo $line1
1:root:x:0:0:root:/root:/bin/bash
[root@rocky8 ~]# echo ${line1/#root/admin/}
1:root:x:0:0:root:/root:/bin/bash
# #What does the sign begin with

[root@rocky8 ~]# echo ${line/%bash/nologin/}
root:x:0:0:root:/root:/bin/nologin/
# %What does it end with

8.3 find and delete

#Delete the string first matched by pattern in the string represented by var
${var/pattern}

#Delete all strings matched by pattern in the string represented by var
${var//pattern}

#Delete all strings with pattern as the beginning of the line in the string represented by var
${var/#pattern}

#Delete all strings with pattern as the end of the line in the string represented by var
${var/%pattern}

example:

[root@rocky8 ~]# echo ${line/root/}
:x:0:0:root:/root:/bin/bash
[root@rocky8 ~]# echo ${line//root/}
:x:0:0::/:/bin/bash

8.4 character case conversion

#Convert all lowercase letters in var to uppercase
${var^^}

#Convert all uppercase letters in var to lowercase
${var,,}

example:

[root@rocky8 ~]# echo ${line^^} #^^Convert to uppercase
ROOT:X:0:0:ROOT:/ROOT:/BIN/BASH
[root@rocky8 ~]# LINE=`echo ${line^^}`
[root@rocky8 ~]# echo $LINE
ROOT:X:0:0:ROOT:/ROOT:/BIN/BASH
[root@rocky8 ~]# echo ${LINE,,} #,, convert to lowercase
root:x:0:0:root:/root:/bin/bash

9. Advanced variables

9.1 assignment of advanced variables


example:

[root@rocky8 ~]# unset name;cto=${name-'raymond'};echo $cto
raymond
[root@rocky8 ~]# name="";cto=${name-'raymond'};echo $cto

[root@rocky8 ~]# name="boss";cto=${name-'raymond'};echo $cto
boss

[root@rocky8 ~]# unset name;cto=${name:-'raymond'};echo $cto
raymond
[root@rocky8 ~]# name="";cto=${name:-'raymond'};echo $cto
raymond
[root@rocky8 ~]# name="boss";cto=${name:-'raymond'};echo $cto
boss

9.2 advanced variable usage - typed variables

Shell variables are generally typeless, but bash Shell provides declare and typeset commands to specify the type of variables. The two commands are equivalent

declare [option] Variable name

Options:
-r Declare or display read-only variables
-i Defines a variable as an integer
-a Define variables as arrays
-A Defines a variable as an associative array
-f Displays all defined function names and their contents
-F Displays only all function names that have been defined
-x Declare or display environment variables and functions,amount to export
-l Declare variables as lowercase letters declare -l var=UPPER
-u Declare variables in uppercase letters declare -u var=lower

example:

[root@rocky8 ~]# declare -l name=BOSS
[root@rocky8 ~]# echo $name
boss
[root@rocky8 ~]# declare -u name=boss
[root@rocky8 ~]# echo $name
BOSS

9.3 variable indirect reference

9.3.1 eval command

The eval command will scan the command line for all permutations before executing the command. This command is applicable to variables whose function cannot be realized in one scan. This command scans variables twice

example:

[root@rocky8 ~]# echo $name
BOSS
[root@rocky8 ~]# CMD=whoami
[root@rocky8 ~]# echo $CMD
whoami
[root@rocky8 ~]# eval $CMD #eval is scanned twice. The first time, the variable is replaced, and the second time, the result after replacement is executed
root

[root@rocky8 ~]# n=10;for i in {1..$n};do echo $i; done
{1..10}
[root@rocky8 ~]# n=10;for i in `eval echo {1..$n}`;do echo $i; done
1
2
3
4
5
6
7
8
9
10

[root@rocky8 ~]# i=1
[root@rocky8 ~]# j=a
[root@rocky8 ~]# $j$i=hello
-bash: a1=hello: command not found
[root@rocky8 ~]# eval $j$i=hello
[root@rocky8 ~]# echo $j$i
a1
[root@rocky8 ~]# echo $a1
hello

9.3.2 indirect variable reference

If the value of the first variable is the name of the second variable, referencing the value of the second variable from the first variable is called indirect variable reference. The value of variable1 is variable2, and variable2 is the variable name. The value of variable2 is value. Indirect variable reference refers to the behavior of obtaining variable value through variable1

variable1=variable2
variable2=value

bash Shell provides two formats for indirect variable reference

#Method 1
#Variable assignment
eval tempvar=\$$variable1
#Display value
eval echo \$$variable1
eval echo '$'$variable1

#Method 2
#Variable assignment
tempvar=${!variable1}
#Display value
echo ${!variable1}

example:

[root@rocky8 ~]# x=y
[root@rocky8 ~]# y=100
[root@rocky8 ~]# echo $x
y
[root@rocky8 ~]# eval echo \$$x
100

[root@rocky8 ~]# eval echo $$x
2417x
[root@rocky8 ~]# echo $$
2417

[root@rocky8 ~]# echo ${!x}
100

Example: batch create user

[root@rocky8 ~]# vim eval_createuser.sh
#!/bin/bash
#
#**********************************************************************************************
#Author:        Raymond
#QQ:            88563128
#Date:          2021-10-22
#FileName:      eval_createuser.sh
#URL:           raymond.blog.csdn.net
#Description:   The test script
#Copyright (C): 2021 All rights reserved
#*********************************************************************************************
n=$#
[ $n -eq 0 ] && { echo "Usage: `basename $0` username..." ; exit 2; }

for i in `eval echo {1..$n}`;do
    user=${!i}
    id $user &> /dev/null && echo $user is exist || { useradd $user; echo $user is created; }
done

[root@rocky8 ~]# bash eval_createuser.sh tom jack bob
tom is created
jack is created
bob is created

Topics: Operation & Maintenance bash architecture DevOps Cloud Native