Linux Bash script advanced tutorial learning

The technical skills here were originally from Google's "Testing on the Toilet" (TOTT). Here is a revised and expanded version.

Script security

All my bash scripts start with the following sentences:

#!/bin/bashset -o nounsetset -o errexit

Doing so will avoid two common problems:

Reference undefined variable (default is "")

Failed command is ignored

It should be noted that some of the Linux command parameters can force the occurrence of errors to be ignored, such as "mkdir -p" and "rm -f".

Also note that in the "errexit" mode, although errors can be effectively captured, all failed commands cannot be captured. In some cases, some failed commands cannot be detected. (For more details, please refer to this post.)

Script function

In bash you can define functions that are just like any other command and are free to use; they make your script more readable:

ExtractBashComments() { egrep "^#"}cat myscript.sh | ExtractBashComments | wccomments=$(ExtractBashComments < myscript.sh)

There are some examples:

SumLines() { # iterating over stdin - similar to awk local sum=0 local line=”” while read line ; do sum=$((${sum} + ${line})) done echo ${sum}}SumLines < data_one_number_per_line.txtlog() { # classic logger local prefix="[$(date +%Y/%m/%d\ %H:%M:%S)]: " echo "${prefix} $@" > &2}log "INFO" "a message"

Move your bash code as much as possible into the function, placing only global variables, constants, and statements that call "main" on the outermost layer.

Variable annotation

Bash can make limited comments on variables. The two most important annotations are:

Local (function internal variable)

Readonly (read-only variable)

# a useful idiom: DEFAULT_VAL can be overwritten# with an environment variable of the same namereadonly DEFAULT_VAL=${DEFAULT_VAL:-7}myfunc() {# initialize a local variable with the global default local some_var=${DEFAULT_VAL} ... }

In this way, you can declare a variable that was not previously a read-only variable as a read-only variable:

x=5x=6readonly xx=7 # failure

Try to use local or readonly annotations for all variables in your bash script.

Use $() instead of backquote (`)

Anti-single quotes are ugly. In some fonts, they are similar to single quotes. $() can be used inline, and it avoids the hassle of escapes.

# both commands below print out: ABC-Decho "A-`echo B-\`echo C-\\\`echo D\\\````"echo "A-$(echo B-$(echo C- $(echo D)))"

Replace [[]] (double brackets) with []

Using [[]] can avoid problems like abnormal file extensions, and it can bring a lot of syntax improvements, but also adds a lot of new features:

Single brackets:

[ "${name}" \> "a" -o ${name} \< "m" ]

Double brackets

[[ "${name}" > "a" && "${name}" < "m" ]]

Regular Expressions/Globbing

The benefits of using double brackets are best represented by the following examples:

t="abc123"[[ ""tt == abc* ]] # true (globbing comparison)[[ " "" "$t" == "abc*" ]] # false (literal comparison)[[ "$t" = ~ [abc]+[123]+ ]]# true (regular expression comparison)[[ ""$t" =~ "abc*" ]] # false (literal comparison)

Note that starting from bash 3.2, regular expressions and globbing expressions cannot be enclosed in quotation marks. If your expression has spaces, you can store it in a variable:

r="a b+"[[ " "a bbb" =~ $r ]] # true

String comparisons by Globbing can also be used in case statements:

Case $t inabc*) ;;esac

String manipulation

Bash has a variety of ways to manipulate strings, many of which are undesirable.

Basic user

f="path1/path2/file.ext"len="${#f}" # = 20 (string length) # Slicing operation: ${ : } or ${ : : }slice1="${f:6}"# = "path2/file.ext"slice2="${f:6:5}"# = "path2"slice3="${f: -8}"# = "file.ext" (Note: there are spaces before "-") pos=6len=5slice4="${f:${pos}:${len}}"# = "path2"

Replace operation (using globbing)

f="path1/path2/file.ext"single_subst="${f/path?/x}" # = "x/path2/file.ext"global_subst="${f//path?/x}" # = "x/x/file.ext"# string split readonly DIR_SEP="/"array=(${f//${DIR_SEP}/})second_dir="${arrray[1]}" # = path2

Remove head or tail (using globbing)

f="path1/path2/file.ext"# remove the string header extension="${f#*.}" # = "ext"# remove the string header with a greedy match filename="${f##* /}" # = "file.ext"# remove string tail dirname="${f%/*}" # = "path1/path2"# remove greedy match string tail root = ${f%% /*}" # = "path1"

Avoid using temporary files

Some commands require the file name as a parameter so that no pipe can be used. At this point, <()? is useful. It can take a command and convert it to something like a file name:

# Download and compare two web pages diff <(wget -O - url1) <(wget -O - url2)

There is also a very useful "here documents" which allows you to enter multiple lines of string on standard input. The following 'MARKER' can be replaced with any word.

# Any word can be used as delimiter command << MARKER...${var}$(cmd)...MARKER

If there is no inline variable substitution in the text, you can wrap the first MARKER in single quotes:

Command << 'MARKER'...no substitution is happening here.$ (dollar sign) is passed through verbatim....MARKER

Built-in variables

prompt

Using $* is rarely the right choice.

$@ can handle the space parameter, and spaces between parameters can be handled correctly.

When using $@, double quotation marks should be used, like "$@".

debugging

Check the script syntax:

Bash -n myscript.sh

Track the execution of each command in the script:

Bash -v myscripts.sh

Track the execution of each command in the script and attach extension information:

Bash -x myscript.sh

You can use the set -o verbose and set -o xtrace commands in the script header to permanently specify -v and -o. This is useful when executing a script on a remote machine to use it to output remote information.

When should I not use bash scripts

Your script is too long, up to several hundred lines

You need a more complex data structure than an array

Complex escaping issues have arisen

There are too many string operations

Less need to call other programs and interact with other program pipes

Worrying about performance

At this time, you should consider a scripting language such as Python or Ruby.

4000 Puffs Vape

4000 puffs disposable vape pen are so convenient, portable, and small volume, you just need to take them
out of your pocket and take a puff, feel the cloud of smoke, and the fragrance of fruit surrounding you. It's so great.
We are China's leading manufacturer and supplier of disposable vape puff bars, disposable vape 4000 puffs,vape pen 4000 puffs,vape mod 4000 puffs,
big bar vape 4000 puffs,4000 puff rechargeable vape, and e-cigarette kit, and we specialize in Disposable Vapes, e-cigarette vape pens, e-cigarette kits, etc.


disposable vape 4000 puffs,vape pen 4000 puffs,vape mod 4000 puffs,big bar vape 4000 puffs,4000 puff rechargeable vape

Ningbo Autrends International Trade Co.,Ltd. , https://www.mosvapor.com