Http://wiki.ubuntu.org.cn/Shell%E7%BC%96%E7%A8%8B%E5%9F%BA%E7%A1%80
This article Leal
License:
- Authoring Sharing Agreements
- GNU Free Documentation License
Editorial staff: Firehare, Dbzhang800
We can use any kind of text editor, such as Gedit, Kedit, Emacs, VI, etc. to write shell scripts, which must start with the following line (must be placed in the first line of the file):
#!/bin/bash ...
Note: It is best to use "!/bin/bash" instead of "!/bin/sh" if you use TC shell instead of tcsh, other similar.
The symbol #! is used to tell the system which program executes the script, and this example uses/bin/bash. If you want to execute the script after the edit is finished and saved, you must first make it executable:
chmod +x filename
The script is then entered in the directory where the script is located./filename can be executed.
Directory[Hide]
- 1 variable assignments and references
- 2 Process Control in the shell
- 3 && | | operator
- 3.1 Case Statement
- 3.2 SELECT statement
- 3.3 While/for Cycle
- 4 Some special symbols in the shell
- 5 here Document
- 6 functions in the shell
- 7 command-line arguments
- 8 Shell Script Example
- 8.1 General Programming steps
- 8.2 Binary to decimal conversion
- 8.3 file Looping copy
- 9 Script Debugging
|
[edit] variable assignments and references
In shell programming, the use of variables without prior declaration, and the name of the variable names should follow the following rules:
- The first character must be a letter (a-z,a-z) or _
- Cannot have spaces in the middle, you can use underscores (_)
- Cannot use other punctuation
When you need to assign a value to a variable, you can write:
To take the value of a variable, simply precede the variable name with a $ (note: When assigning a value to a variable, you cannot leave spaces on the "=" side)
#!/bin/bash# assigning values to variables: a= "Hello World" #等号两边均不能有空格存在 # Print the value of variable A: echo "A is:" $a
Choose your favorite editor, enter the above, save as file first, then execute chmod +x first to make it executable, and finally enter./first executes the script. The output results are as follows:
A Is:hello World
Sometimes variable names can be confused with other words, such as:
Num=2echo "The $numnd"
The above script does not output "This is the 2nd" but "This is the", because the shell is going to search for the value of the variable numnd, but in fact the variable does not have a value at this time. At this point, we can use curly braces to tell the shell that the NUM variable is to be printed:
Num=2echo "This is the ${num}nd"
The result is: the 2nd
Note the position of the curly braces:
Num=2echo "This is the {$num}nd"
The result of the output: This is the {2}nd
It is important to note that the default assignment for the shell is a string assignment. Like what:
var=1var= $var +1echo $var
The print is not 2 but the same. There are several ways to achieve the effect we want:
Let "Var+=1" var= "$[$var +1]" ((var++)) var=$ (($var + 1)) var= "$ (expr" $var "+ 1)" #不建议使用var = "Expr" $var "+ 1" "#强烈不建议使用, Note the spaces on either side of the plus sign, or assign a value as a string, ' below ESC ', not single quote '.
Note: The first 2 methods are active under bash, and errors occur under SH.
Let represents mathematical operations, and expr is used for integer numeric operations, each of which is separated by a space, $[] The expression in parentheses is evaluated as a mathematical operation before the result is output.
Many of the variables in the shell scripts are automatically set by the system, and we'll explain them when we use them. In addition to the normal shell variables that are only valid within the script, there are environment variables, those that are processed by the Export keyword. Environment variables are not discussed in this article because they are typically used only in logon scripts.
[edit]Process Control in the shell
[Edit]if statement
If expression if the condition is true, then the following part is executed:
If ....; Then ..... elif ...; then ... else .... fi
In most cases, test commands can be used to test conditions, such as the ability to compare strings, to determine whether a file exists and to be readable, and so on ... Usually "[]" to indicate the condition test, note that the space here is important, to ensure that the space before and after the square brackets.
-
[-F "somefile"]: Determine if it is a file
-
[-X "/bin/ls"]: Determine if/bin/ls exists and has executable permissions
-
[-N ' $var]: Determine if the $var variable has a value
-
["$a" = "$b"]: Determine if $ A and $b are equal
Execute man test to see the types that all test expressions can compare and judge. The following is a simple if statement:
#!/bin/bashif [${shell} = "/bin/bash"]; Then echo "Your login shell was the bash (Bourne again shell)" Else echo "Your login shell is not bash but ${shell}" Fi
The variable $shell contains the name of the login shell, which we compare with/bin/bash to determine if the currently used shell is bash.
[edit]&& | | operator
A friend familiar with C might like the following expression:
[-F "/etc/shadow"] && echo "This computer uses shadow passwords"
The && here is a shortcut operator, and if the expression on the left is true then the statement on the right is executed, you can also think of it as a logical operation. The script above indicates that if the/etc/shadow file exists, print "This computer uses shadow passwords". Also in shell programming you can use or manipulate (| |), for example:
#!/bin/bashmailfolder=/var/spool/mail/james[-R "$mailfolder"] | | {echo "Can not read $mailfolder"; exit 1;} echo "$mailfolder have mail from:" grep "^from" $mailfolder
The script first determines whether the mailfolder is readable and prints the line that begins with "from" in the file if it is readable. If unreadable or the operation takes effect, the script exits after the error message is printed. It should be noted that here we have to use the following two commands:
-
-Print error message
-
-Exit Program
We use curly braces to put two commands together as a command in the form of an anonymous function, and the normal function is explained later. We can do anything with an if expression, even if we don't use the and and or operators, but it's much more convenient to work with or operators.
[Edit] Casestatement
The case expression can be used to match a given string instead of a number (not to be confused with Switch...case in C).
Case ... ) do something here ;; Esac
The file command can identify the files of a given file type, such as: File lf.gz, whose output is:
Lf.gz:gzip compressed data, deflated, original Filename,last Modified:mon, 23:09:18 2001, Os:unix
We use this to write a script called Smartzip, which automatically extracts compressed files of bzip2, gzip, and zip types:
#!/bin/bash ftype= "$ (file" $ ")" case "$ftype" in "$1:zip Archive" *) Unzip "$";; "$1:gzip Compressed" *) gunzip "$";; "$1:bzip2 Compressed" *) bunzip2 "$";; *) echo "File" can not is uncompressed with smartzip "; Esac
You may notice that a special variable is used above that contains the first parameter value passed to the script. In other words, when we run:
Smartzip Articles.zip
$ $ is the string articles.zip.
[Edit]SELECT statement
The select expression is an extended application of bash and specializes in interactive situations. Users can choose from a different set of values:
Select Var in ...; Do Break;done ... now $var can is used ....
The following is a simple example:
#!/bin/bashecho "What is your favourite OS?" Select Var in "Linux", "Gnu Hurd" "Free BSD" and "other"; Do Break;doneecho "You have selected $var"
The script runs with the following results:
What are your favourite os?1) Linux2) Gnu Hurd3) free BSD4) other#? 1You has selected Linux
[edit]while/for loop
In the shell, you can use the following loops:
While ...; Do .... Done
As long as the test expression condition is true, the while loop runs all the time. The keyword "break" is used to jump out of a loop, and the keyword "continue" can skip the rest of a loop and jump directly to the next loop.
The For loop looks at a list of strings (strings are separated by spaces) and assigns them to a variable:
for Var in ...; Do .... Done
The following example prints a B c to the screen separately:
#!/bin/bashfor var in A B C; Do Echo ' var is $var ' done
The following is a useful script showrpm, which functions to print some RPM package statistics:
#!/bin/bash# List A content summary of a number of RPM packages# usage:showrpm rpmfile1 rpmfile2 ... # example:showrpm/c Drom/redhat/rpms/*.rpmfor rpmpackage in "[email protected]"; Do if [-R ' $rpmpackage "];then echo" =============== $rpmpackage ============== " rpm-qi-p $rpmpackage else echo "error:cannot Read file $rpmpackage" Fidone
Here comes the second special variable [email protected], which contains all the command-line parameter values entered. If you run showrpm openssh.rpm w3m.rpm webgrep.rpm, then "[Email protected]" (with quotation marks) contains 3 strings, namely openssh.rpm, w3m.rpm, and webgrep.rpm. The meaning of $* is similar. But there is only one string. If no quotes are quoted, the parameters with spaces are truncated.
[Edit]some special symbols in the shell
[edit] quotation marks
The program expands wildcard characters and variables before passing any parameters to the program. The so-called extension means that the program will replace the wildcard characters (such as *) with the appropriate file name and replace the variable with the variable value. We can use quotation marks to prevent this extension, let's take a look at an example, assuming there are two JPG files in the current directory: Mail.jpg and tux.jpg.
#!/bin/bashecho *.jpg
The result of the operation is:
Mail.jpg tux.jpg
quotation marks (single and double quotation marks) prevent the expansion of the wildcard character *:
#!/bin/bashecho "*.jpg" Echo ' *.jpg '
The result of this operation is:
*.jpg*.jpg
Where single quotes are more restrictive, it prevents any variable extension, and double quotes prevent wildcard expansion but allow variable expansion:
#!/bin/bashecho $SHELLecho "$SHELL" Echo ' $SHELL '
The result of the operation is:
/bin/bash/bin/bash$shell
There is also a way to prevent this extension by using the escape character-the backslash: \:
echo \*.jpgecho \ $SHELL
The output is:
*.jpg$shell
[edit] hereDocument
It is a good idea to use here document when you want to pass a few lines of text to a command. Writing a helpful text for each script is useful if you use here document without having to use the Echo function to output a line. Here document begins with <<, followed by a string, which must also appear at the end of here document. Here is an example where we rename multiple files and use the here document to print help:
#!/bin/bash# we have less than 3 arguments. Print the Help text:if [$#-lt 3] ; Thencat << Helpren--renames a number of files using sed regular expressions Usage:ren ' regexp ' replacement ' file S ... Example:rename all *. HTM files in *.html:ren ' htm$ ' html ' *. Htmhelp #这里HELP要顶格写, there must be no spaces or tab tabs in front. If the cat line is written as Cat <<-help, the Front tab is available. Exit 0fiold= "$" new= "$" # The SHIFT command removes one argument from the list of# command line arguments.shiftshift# [EMA Il protected] contains now all the Files:for file in "[email protected]"; do if [-F ' $file "] ; Then newfile= ' echo ' $file | Sed "s/${old}/${new}/g" ' if [-f ' $newfile ']; Then echo "ERROR: $newfile exists already" else echo "renaming $file to $newfile ..." MV "$file "$newfile" fi fidone
The example is a bit complicated and we need to spend more time explaining it. The first if expression determines whether the input command-line argument is less than 3 (the special variable $# represents the number of parameters included). If the input parameter is less than 3, the help text is passed to the Cat command, which is then printed on the screen by the cat command. The program exits after printing the help text. If the input parameter is equal to or greater than 3, we assign the first parameter to the variable old and the second parameter to the variable new. Next, we use the shift command to remove the first and second arguments from the argument list, so that the third argument becomes the first parameter of the argument list $*. Then we start the loop, and the command-line argument list is assigned to the variable $file one by one. We then determine if the file exists and, if it exists, it is searched and replaced by the SED command to generate a new file name. The command result in the backslash is then assigned to NewFile. So we get to the end: we got the old filename and the new file name. Then use the MV command to rename
[edit]functions in the shell
If you have written more complex scripts, you may find that you can use the same code in several places, which is a lot easier if you use the function. The function has the following approximate appearance:
FunctionName () {# Inside the body $ is the first argument given to the function# $ the second ... body}
function does not need to be declared. As long as the definition appears before execution.
The following is a script named Xtitlebar that can change the name of the terminal window. A function called Help is used here, which is used two times in the script:
Providing help in a script is a good programming habit that makes it easier for other users (and themselves) to use and understand scripts.
[Edit] command-line arguments
We've seen $* and $ $ ... $9 and other special variables that contain the parameters that the user entered from the command line. So far, we've only learned a few simple command-line syntax (such as some mandatory parameters and the-h option for viewing help). But when you're writing more complex programs, you may find that you need more custom options. The usual practice is to add a minus sign before all optional arguments, followed by a parameter value (such as a file name).
There are many ways to analyze input parameters, but the following example of using case expressions is a good idea.
#!/bin/bash Help () { cat << help- generic command line parser demo. USAGE example:cmdparser-l hello-f---somefile1 somefile2help exit 0} while [-N "$"]; Docase "$" in- h) Help;shift 1;; # function Help is called- f) Opt_f=1;shift 1; # variable Opt_f is set- L) Opt_l=$2;shift 2; #-L takes an argument, shift by 2 --shift;break; # End of options -*) echo "error:no such option $. -H for Help "; exit 1;; *) break;; Esacdone echo "Opt_f is $opt _f" echo "opt_l are $opt _l" echo "First arg is $" echo "2nd Arg is $"
You can run the script this way:
Cmdparser-l hello-f---somefile1 somefile2
The returned results are as follows:
Opt_f is 1opt_l are hellofirst arg is-somefile12nd arg is somefile2
How does this script work? The script first loops through all the input command-line arguments, compares the input parameters to the case expression, sets a variable if the match, and removes the argument. According to the practice of UNIX systems, the first entry should be a parameter that contains a minus sign.
[edit]Shell script example
[Edit] general programming steps
Now let's discuss the general steps for writing a script. Any good script should have help and input parameters. Writing a framework script (framework.sh), which contains the framework structure required for most scripts, is a very good idea. This way, when we start writing a new script, we can first execute the following command:
CP framework.sh MyScript
And then insert your own function.
Let's take a look at the following two examples.
[edit] binary to decimal conversion
The script b2d converts the binary number (for example, 1101) to the corresponding decimal number. This is also an example of a mathematical operation with the expr command:
#!/bin/bash# vim:set sw=4 ts=4 et:help () {cat << help b2d--convert binary to decimal usage:b2d [-h] Binarynu M OPTIONS:-H Help text example:b2d 111010will return 58HELP exit 0} error () {# Print an error and exit Echo ' $ ' Exit 1} lastchar () {# return the last character of a, string in $rval if [-Z ' $ ']; then # empty string RV Al= "" Return fi # WC puts some space behind the output this is why we need sed:numofchar= ' echo-n ' | Sed ' s///g ' | Wc-c ' # Now cut out of the last char rval= ' echo-n ' | Cut-b $numofchar '} chop () {# Remove the last character in string and return an IT in $rval if [-z] $ '; then # E Mpty string rval= "" Return fi # WC puts some space behind the output this was why we need sed:numofchar= ' E Cho-n "$" | wc-c | Sed ' s///g ' if ["$numofchar" = "1"]; Then # only one char in string rval= "" Return fi numofcharminus1= ' expr $numofchar "-" 1 ' # now cut AL L BUT the Last char:rval= ' Echo-n ' | Cut-b-$numofcharminus 1 ' #原来的 rval= ' echo-n | Cut-b 0-${numofcharminus1} ' run-time error. #原因是cut从1开始计数, it should be Cut-b 1-${numofcharminus1}} While [-N "$"]; Docase $ in-h) Help;shift 1;; # function Help is called--) Shift;break; # End of options-*) error "error:no such option $. -H for help ";; *) break;; esacdone# the main programsum=0weight=1# one arg must be given:[-Z "$"] && helpbinnum= "$" binnumorig= "$" while [-N "$binnum"]; Do Lastchar "$binnum" if ["$rval" = "1"]; Then sum= ' expr ' $weight ' "+" "$sum" ' fi # Remove the last position in $binnum chop "$binnum" binnum= "$rval" weight= ' expr ' $weight ' "*" 2 ' done echo "binary $binnumorig is decimal $sum" #
The algorithm used by the script is to take advantage of decimal and binary number weights (1,2,4,8,16,..), such as the binary "10" can be converted to decimal:
0 * 1 + 1 * 2 = 2
In order to get a single binary number we are using the Lastchar function. The function uses Wc–c to calculate the number of characters, and then uses the Cut command to remove the end character. The function of the chop function is to remove the last character.
[edit] file loop copy
You may have this requirement and always do this: Save all sent messages to a file. But after a few months, the file may become so large that the file's access slows down, and the following script rotatefile can fix the problem. This script can rename the message to save the file (assuming outmail) as OUTMAIL.1, and the original OUTMAIL.1 becomes outmail.2 and so on ...
#!/bin/bash# vim:set sw=4 ts=4 et:ver= "0.1" help () {cat << help Rotatefile--Rotate the file name USAGE : Rotatefile [-h] filename OPTIONS:-H Help text example:rotatefile out this would e.g rename out.2 to Out.3, Out.1 To Out.2, out to OUT.1[BR] and create a empty out-file the max number is version $verHELP exit 0} error () { echo "$" exit 1} While [-N "$"]; Do case $ in-h) Help;shift 1;; --) break;; -*) echo "error:no such option $. -H for Help "; exit 1;; *) break;; Esacdone # input Check:if [-Z "$"] ; Then error ' error:you must specify a file, use-h for help "fi filen=" $ "# Rename any. 1,. 2 etc file:for N in 9 8 7 6 5 4 3 2 1; do if [-f ' $filen. $n "]; Then p= ' expr $n + 1 ' echo ' mv $filen. $n $filen. $p "MV $filen. $n $filen. $p Fidone # Rename the original fi Le:if [-F "$filen"]; Then echo "MV $filen $filen. 1" MV $filen $filen. 1fi echo Touch $filentouch $filen
How does this script work? After the user has been provided with a file name, a loop of 9 to 1 is first performed, and the file name. 9 is renamed to the file name. 10, the file name. 8 is renamed as the file name. 9 ... Wait a minute. After the loop is finished, name the original file as the file name. 1, create an empty file with the same name as the original file (Touch $filen)
[Edit] script debugging
The simplest way to debug is, of course, to use the echo command. You can use Echo to print variable values in any place where you suspect it's wrong, which is why most shell programmers spend 80% of their time debugging. The advantage of Shell scripting is that there is no need to recompile, and it does not take much time to insert an echo command.
The shell also has a real debug mode, if the script "Strangescript" error, you can use the following command to debug:
Sh-x Strangescript
7 The preceding command executes the script and displays the values of all variables.
The shell also has a pattern that does not execute the script to check only the syntax, and the command is as follows:
Sh-n Your_script
This command returns all syntax errors.
We hope you can start writing your own shell scripts now, and enjoy the fun! :)
Shell Programming Basics