Bash Script Learning notes Quick Start article

Source: Internet
Author: User
Tags case statement data structures echo b echo d regular expression

Script Security

All of my bash scripts start with the following lines:

The code is as follows Copy Code

#!/bin/bash
Set-o Nounset
Set-o Errexit

Doing so avoids two common problems:

Reference to an undefined variable (the default value is "")

Commands that failed to execute are ignored

It should be noted that some of the parameters of some Linux commands can be enforced to ignore errors such as "Mkdir-p" and "rm-f".

Also note that in the "Errexit" mode, although it is effective to catch errors, but not all failed to capture the command, in some cases, some failed commands are not detected. (For more details, please refer to this post.) )
Script functions

In bash you can define functions that, like any other command, can be used arbitrarily; they make your script more readable:

The code is as follows Copy Code

Extractbashcomments () {
Egrep "^#"
}
Cat myscript.sh | extractbashcomments | Wc
comments=$ (Extractbashcomments < myscript.sh)

There are also some examples:

  code is as follows copy code

Sumlines () {   # iterating over Stdin-similar to awk     
    local sum=0
  ;   local line= ""
    while read line; does
        sum=$ ((${sum} + ${line}))
    done
    echo ${sum}
}
Sumlines < Data_one _number_per_line.txt
Log () {  # Classic Logger
   local prefix= "[$ (date +%y/%m/%d%h:%m:%s)]:"
   echo "${prefix} $@" >&2
}
Log "INFO" "a Message"

Move your bash code as far as possible into a function, placing only the global variables, constants, and statements that are called to "main" on the outermost layer.
Variable annotation

In bash, you can make limited annotations to variables. The most important two annotations are:

Local (function internal variables)

ReadOnly (read-only variable)

The code is as follows Copy Code

# A useful idiom:default_val can be overwritten
# with an environment variable of the same name
ReadOnly 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 a read-only variable as a read-only variable:

The code is as follows Copy Code

X=5
X=6
ReadOnly x
X=7 # failure

Try to annotate all variables in your bash script with local or readonly.
Use $ () instead of inverted single quotes (')

Inverted single quotes are hard to read and are similar in some fonts to positive single quotes. $ () can be used inline and avoids the hassle of escape characters.

The code is as follows Copy Code

# both commands below print out:a-b-c-d
echo "A-' echo-B ' echo c-\ ' echo d\ '" "
echo "a-$ (Echo b-$ (echo D))"

Replace with [[]] (double bracket) []

using [[]] avoids problems like the file name extension of an exception, and it can lead to a lot of grammatical improvements, and adds a lot of new features:
operator function Description
|| Logical OR (used in double brackets only)
&& logical AND (used in double brackets only)
< string comparisons (no transfer required in double brackets)
-LT Digital Comparison
= String Equal
= = globbing string comparison (only used in double brackets, reference below)
=~ uses regular expressions for string comparisons (use in double brackets only, reference below)
-N Non-empty string
-Z Empty string
-eq numbers equal
-ne numbers Range
Single bracket:

The code is as follows Copy Code

["${name}" > "A"-O ${name} < "M"]

Double Middle bracket:

The code is as follows Copy Code

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

Regular Expression/globbing

The benefits of using double brackets are best illustrated with the following examples:

The code is as follows Copy Code

t= "Abc123"
[[$t ' = = abc*]] # True (globbing comparison)
[[' $t ' = = ' abc* ']] # false (literal comparison)
[[' $t ' =~ [abc]+[123]+]] # True (regular expression comparison)
[[' $t ' =~ ' abc* ']] # false (literal comparison)

Note that, starting with Bash version 3.2, regular and globbing expressions cannot be wrapped in quotes. If you have a space in your expression, you can store it in a variable:

The code is as follows Copy Code

R= "a B +"
[["A BBB" =~ $r]] # True

String comparisons by globbing can also be used in a case statement:

The code is as follows Copy Code

Case $t in
abc*) <action>;
Esac

String manipulation

There are a variety of ways to manipulate strings in bash, many of which are undesirable.

Basic User

The code is as follows Copy Code

f= "Path1/path2/file.ext"
Len= "${#f}" # = 20 (string length)
# slice operation: ${<var>:<start>} or ${<var>:<start>:<length>}
slice1= "${f:6}" # = "Path2/file.ext"
Slice2= "${f:6:5}" # = "path2"
Slice3= "${f:-8}" # = "File.ext" (Note: "-" before a space)
Pos=6
Len=5
Slice4= "${f:${pos}:${len}}" # = "path2"

Replace operation (using globbing)

The code is as follows Copy Code

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)

The code is as follows Copy Code

f= "Path1/path2/file.ext"
# Delete String headers
Extension= "${f#*.}" # = ' ext '
# Remove string headers in greedy match
Filename= "${f##*/}" # = "File.ext"
# Delete String tail
Dirname= "${f%/*}" # = "Path1/path2"
# to remove the tail of a string in a greedy match
root= "${f%%/*}" # = "path1"

Avoid using temporary files

Some commands require a file name as a parameter, so you cannot use the pipe. This time < () is useful, it can accept a command and convert it into something that can be a filename or something:

#

The code is as follows Copy Code
Download and compare two pages
Diff < (Wget-o-URL1) < (Wget-o-URL2)

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

The code is as follows Copy Code

# any word can be used as a delimiter
Command << MARKER
...
${var}
$ (CMD)
...
MARKER

If there are no inline variable substitution operations in the text, you can wrap the first marker in single quotes:

The code is as follows Copy Code

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

Built-in variables
Variable description
$ script Name
The nth argument passed to the script/function $n
PID for $$ scripts
$! PID of the last executed command (process running in background)
$? Exit status of previous command (Pipe command using ${pipestatus})
$# number of arguments passed to a script/function
$@ all parameters passed to the script/function (identifying each parameter)
$* all arguments passed to the script/function (take all parameters as a string)

Tips

Using $* is rarely the right choice.

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

Use $@ should be enclosed in double quotes, like "$@".
Debugging

To perform a syntax check on a script:

The code is as follows Copy Code

Bash-n myscript.sh

Trace the execution of each command in the script:

The code is as follows Copy Code

Bash-v myscripts.sh

Trace the execution of each command in the script and append the extension information:

The code is as follows Copy Code

Bash-x myscript.sh

You can use Set-o verbose and set-o xtrace to permanently specify-V and-O in the script header. This is useful when executing a script on a remote machine, using it to output remote information.
When should you not use bash scripts

Your script is too long, up to hundreds of lines

You need more complex data structures than arrays.

A complex escape problem has occurred

There are too many string operations

Less need to invoke other programs and interact with other program pipelines

Worry about performance

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

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.