Shell Programming (1) (2) (3)

xiaoxiao2021-03-06  73

Source: www.iselong.com Abstract: This article combines a lot of examples to explain how to write a shell script. (2002-09-16 13:27:24) Why do shell programming in a Linux system, although there are a variety of graphical interface tools, but shell is still a very flexible tool. Shell is not only a collection of commands, but also a great programming language. You can use shell to automate a large number of tasks, Shell is particularly good at system management tasks, especially for more important tasks that are more important, maintainability, and portability. Below, let's take a look at how shell works: Building a script Linux has a lot of different shells, but usually we use Bash (Bash Again Shell) for shell programming, because Bash is free and easy to use. So the scripts provided in this article are bash (but in most cases, these scripts can also run in Bash's big sister, Bourne Shell). Like other languages, we use any of the text editor, such as Nedit, Kedit, Emacs, VI, etc. to write our shell programs. The program must start with the following row (must be in the first line of the file): #! / Bin / sh symbol #! Used to tell the system that the parameters behind it are used to execute the file. In this example we use / bin / sh to execute the program. When editing the script, if you want to execute this script, you must also make it executable. To make the script execut: chmod x filename then, you can perform your script by entering: ./filename. Note When the SHELL programming is performed, the sentence indicates the sentence until the end of this line. We sincerely recommend that you use comments in the program. If you use a comment, even if you don't use this script, you can understand the role and working principle of this script in a short period of time. Variables You must use variables in other programming languages. In the shell program, all variables are composed of strings and you do not need to declare variables. To assign a value to a variable, you can write: Variable name = value Take out variable value can add a dollar sign ($) in front of the variable: #! / Bin / sh # Assignment value: a = "Hello World" # Now print The contents of the variable A: echo "a is:" Echo $ A Enter the above in your editor, then save it as a file first. After the CHMOD X first is executed, it can be executed, and finally input ./first executes the script. This script will output: a is: Hello World Sometimes it is easy to confuse with other words, such as: Num = 2echo "this is the $ numnd" This does not print "this is the 2nd", but only print "this is the", because the shell will go to the value of the variable Numnd, but there is no value at this variable. You can use the curly bracket to tell Shell, what we want to print is NUM variable: Num = 2echo "this is the $ = 2echo" this is the $ {num} nd "This will print: this is the 2nd has a number of variables are automatically set, this will be behind Discussions are discussed when using these variables.

If you need to process mathematical expressions, you need to use programs such as EXPR (see below). In addition to the general SHELL variables only in the program, there are environment variables. Variables processed by the export keyword are called environment variables. We don't discuss environment variables because usually use environment variables only in the login script. Shell Commands and Process Control You can use three types of commands in the shell script: 1) UNIX command: Although any UNIX command can be used in the shell script, it is still a relatively more common command. These commands are usually used for files and text operations. Commonly used command syntax and function echo "some text": Print text content on the screen LS: file list wc -l filewc -w filewc -c file: calculate the number of words in the single word calculation file in the file line count CP SourceFile Destfile: File Copy MV OldName NEWNAME: Rename file or mobile file RM file: Delete file Grep 'Pattern' file: Search strings in the file such as: grep 'searchstring' file.txt cut -b colnum file: specify desired display The file content range, and output them to standard output devices such as: Output Each line of the 5th to nine characters CUT -B5-9 file.txt must not be confused with the CAT command, this is two completely different commands CAT file.txt: Output file content to the standard output device (screen) File Somefile: Get file type read var: prompt user input, and assign the input to the variable sort file.txt: Sort the line in the file.txt file UNIQ: Deleting the ranks of the text file, such as: sort file.txt | UNIQ EXPR: Mathematical operations EXAMPLE: Add 2 and 3EXPR 2 " " 3 Find: Search files such as: Search Find. -name filename -print TEE: Output data to standard output devices (screens) and files, such as: SomeCommand | Tee Outfile Basename file: Return file names that do not contain paths such as: baseName / BIN / TUX will return Tux DirName File: Return to files, such as: DIRNAME / bin / tux will return / bin head file: Print text files a few lines of tail file: Print text files Several lines of SED: SED is a basic lookup replacement. You can read text from standard inputs (such as command pipes), and output the result to the standard output (screen). This command is searched using a regular expression (see). Don't confuse the wildcards in the shell. For example: replace LinuxFocus with LinuxFocus: cat text.file | SED '> NewText.File awk: awk to extract fields from text files. By default, the field split is a space, you can use -f to specify other splites. Cat file.txt | awk -f, '{print $ 1, "$ 3}" We use, as a field split, and print one and the third field.

If the contents are as follows: Adam Bor, 34, Indiakerry Miller, 22, USA command output: Adam Bor, Indiakerry Miller, USA2) Concept: pipe, redirect, and backtick These are not system commands, but they are really important. The pipe (|) uses the output of a command as the input of another command. GREP "Hello" file.txt | wc -l Search in file.txt and contains a row with "Hello" and calculates the number of rows. The output of the grep command here as the input of the WC command. Of course you can use multiple commands. Redirection: Output the result of the command to the file instead of the standard output (screen). > Write files and override the old file >> Add to the end of the file, keep the old file content. Reverse shorting of slashes Use the short-shot slash to output an order of the output as a command line parameter of another command. Command: find. -Mtime -1 -type f -print Used to find files that have been modified within the last 24 hours (-mtime -2 indicating over the past 48 hours). If you want to make all the finded files a package, you can use the following scripts: #! / Bin / sh # the ticks are backticks (`) NOT NORMAL quotes ('): tar -zcvf lastmod.tar.gz` find . -mtime -1 -type f -print` 3) Process Control "IF" expression If the condition is true, the part is executed behind: if ....; the .... Elif ....; ... Else .... Fi Most of the cases, you can use the test command to test the condition. For example, you can compare the string, determine if the file exists and whether it is readable, and so on ... usually use "[]" to represent the condition test. Note that the space here is important. To ensure the space of square brackets. [-f "somefile"]: Judging whether it is a file [-x "/ bin / ls"]: Judgment / bin / LS exists and has executable permissions [-n "$ var"]: Determine if the $ VAR variable is Value ["$ a" = "$ b"]: Judging whether $ A and $ B are equal to MAN Test to view all test expressions to compare and judgment types. Perform the following scripts directly: #! / Bin / shif ["$ shell" = "/ bin / bash"]; then echo "Your login shell is the bash (bourne again shell)" Else Echo "Your Login Shell Is Not Bash But $ Shell "Fi Variable $ shell contains the name of the login shell, we compare it with / bin / bash.

/ ***************************************************** / shortcut operator is familiar with C Language friends may like the following expressions: [-f "/ etc / shadow"] && echo "this computer buy shadow passwors" here && is a shortcut, if the expression on the left is true to the right Scriptures. You can also think that it is a logical operation. In the above example, if the / etc / shadow file exists, "this Computer Uses Shadow PassWors" is printed. Also or operate (||) is also available in shell programming. Here is an example: #! / Bin / shmailfolder = / var / spool / mail / james [-r "$ mailfolder"] '' {echo "can not read $ mailfolder"; exit 1;} echo "$ mailfolder Has Mail From: "GREP" ^ from "$ mailfolder This script first determines whether MailFolder is readable. If readable, print "from" one line in the file. If you do not read or operate, the script exits after the error message is printed. There is a problem here, that is, we must have two commands: - Print Error Message - Exit User We use the curb brackets to put two commands together as an anonymous function as a command. The general function will be mentioned below. Don't use and or operate, we can also use IF expressions, but use or operators will be more convenient. The CASE expression can be used to match a given string instead of a number. Case ... in ...) Do Something Here ;; ESAC let us see an example. File commands can distinguish a file type of a given file, such as File Lf.gz will return: lf.gz: gzip compressed data, deflated, Original FileName, Last Modified: Mon Aug 27 23:09:18 2001, OS : UNIX We used this to write a script called Smartzip, which can automatically extract the compressed files of Bzip2, Gzip, and Zip type: #! / Bin / shftype = `file" $ 1 "` case "$ ftype" in "$ 1 : Zip archive "*) unzip" $ 1 ";; $ 1: gzip compressed" *) Gunzip "$ 1" ;; $ 1: bzip2 compressed "*) Bunzip2" $ 1 ";; *) error" File $ 1 can not be uncompressed WITH Smartzip ";; ESAC You may notice that we use a special variable $ 1 here. This variable contains the first parameter value passed to the program. That is, when we run: Smartzip Articles.zip $ 1 is a string Articles.zip SELECT expression is an extension application of Bash, especially in interactive use. Users can choose from a set of different values.

SELECT VAR IN .... DO BREAKDONE .... NOW $ VAR CAN BE Used .... Below is an example: #! / bin / shecho "What is your favorite OS?" Select Var in "Linux" GNU Hurd "Free BSD" "other"; do Breakdoneecho "You Have SELECTED $ VAR" below is the result of this script running: What is your favorite OS? 1) Linux2) Gnu Hurd3) Free BSD4) Other #? 1you Have SELECTED Linux You can also use the following loop expressions in the shell: While ...; do .... done while-loop will run until the expression test is true. Will Run While The Expression That We Test for Is True. Keyword "BREAK" is used to jump out of the loop. The keyword "continue" is used to directly skip to the next loop directly. For-loop expressions see a string list (string space separated) and then assign it to a variable: for var in ....; do .... DONE in the example below, will print ABC to On the screen: #! / Bin / shfort; do echo "VAR I $ VAR" DONE The following is a more useful script showrpm, its function is to print some RPM packages: #! / Bin / sh # List a content summary of a number of rpm packages # usage: showrpm rpmfile1 rpmfile2 ... # example: showrpm / cd/redhat/rpms/*.rpmfor rpmpackage in $ *; do if [-r "$ rpmpackage"]; then echo "=====================================" rpm -qi -p $ rpmpackage else echo "error: Cannot Read File $ RPMPackage "Fidone The second special variable is available here. This variable contains all input command line parameter values. If you run showrpm openssh.rpm w3m.rpm webgrep.rpm, $ * contains 3 strings, ie openssh.rpm, w3m.rpm and webGrep.rpm. Quotation marks extend wildcard before passing any parameters to programs. And variables. The so-called extension here is that the program will replace the wildcard (such as *) to the appropriate file name, and its variable replaces a variable value. In order to prevent this replacement, you can use quotation marks: Let's take an example, assume some files, two JPG files, mail.jpg, and tux.jpg in the current directory. #! / bin / shecho * .jpg This will print the result of "mail.jpg tux.jpg".

Quotation marks (single quotes and double quotes) will prevent this wildcard extension: #! / Bin / shecho "* .jpg" echo '* .jpg' This will print "* .jpg" twice. Single quotes are more stringent. It prevents any variable extensions. Dual quotes can prevent wildcards from expand but allow variables to expand. #! / bin / shecho $ shellecho "$ shell" Echo '$ shell' Run results for: / bin / bash / bin / bash $ shell Finally, there is also a way to prevent this extension, that is, using escape characters - - Anti-ramp: echo * .jpGecho $ shell This will output: *. JPG $ shellhere Documents When you want to pass a few lines to a command, Here Documents (Translator Note: I haven't seen the word suitable for this term) Translation) A nice way. It is useful to write a part of the helpibility for each script. At this time, if we have the four Here Documents, you don't have to use the Echo function to output a row of rows. A "here document" with << starts, after connecting a string, this string must also appear at the end of the Here Document. Here is an example in which we rename multiple files and use Here Documents Print Help: #! / Bin / sh # We Have Less Than 3 Arguments. Print The Help Text: IF [$ # - LT 3]; Thencat

USAGE: REN 'Regexp' 'Replacement' FILES ...

EXAMPLE: RENAME All * .htm files in * .html:

Ren 'htm $' 'html' * .htm

Help

EXIT 0

Fi

OLD = "$ 1"

NEW = "$ 2"

# THE SHIFT COMMAND Removes One Argument from The List of

# Command Line Arguments.

Shift

Shift

# $ * contains now all the files:

For File in $ *; 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

Fi

DONE

This is a complex example. Let us discuss in detail. The first IF expression determines whether the input command line argument is less than 3 (special variable $ # means a number of parameters). If the input parameter is less than 3, the help text is passed to the CAT command, and then print it on the screen by the CAT command. Print help text post-programs exit. If the input parameter is equal to or greater than 3, we assign the first parameter to the variable OLD, and the second parameter assigns the variable New. Next, we use the shift command to remove the first and second parameters from the parameter list, so the original third parameter is the first parameter of the parameter list *. Then we start loop, the command line parameter list is assigned to the Variable $ File by one. Then we determine if the file exists, if there is, search and replace the new file name via the SED command search. Then, the result of the insection of the inside the slash is then assigned to newfile. This way we have achieved our goal: got old file name and new file name. Then use the mv command to rename it. function

If you have written some slightly complex programs, you will find the same code in several places in a few places, and you will find that if we use a function, it will be much more convenient. A function is this look:

FunctionName ()

{

# INSIDE The Body $ 1 Is The First Argument Given to The Function

# $ 2 The second ...

Body

}

You need to declare the function in the beginning of each program.

Below is a script called Xtitlebar, you can change the name of the terminal window using this script. A function called Help is used here. As you can see, this definition function is used twice.

#! / bin / sh

# vim: set sw = 4 Ts = 4 et:

Help ()

{

Cat

Xtitlebar - Change the name of an xterm, gnome-terminal or kde konsole

Usage: Xtitlebar [-h] "string_for_titelbar"

Options: -h Help Text

Example: Xtitlebar "CVS"

Help

EXIT 0

}

# in case of error or if --h is given we call the function help:

[-z "$ 1"] && Help

[$ 1 "=" -h "] && Help

# Send the escape sequence to change the xterm titelbar:

Echo -e "33] 0; $ 107"

#

Providing help in scripts is a good programming habit, so that other users (and you) use and understand scripts.

Command line parameters

We have seen $ * and $ 1, $ 2 ... $ 9 and other special variables, including the parameters input from the command line from the command line. So far, we only understand some simple command line syntax (such as some mandatory parameters and viewing the -h option). But when writing more complex programs, you may find more custom options. The usual convention is to add a minus sign before all optional parameters, and then add the parameter values ​​(such as file name).

There is a lot of ways to achieve analysis of input parameters, but the following examples use case expressions are a nice way.

#! / bin / sh

Help ()

{

Cat

This is a generic commnd line parser demo.

USAGE EXAMPLE: CMDPARSER -L HELLO -F ---SOMEFILE1 Somefile2help

EXIT 0

}

While [-n "$ 1"]; do

Case $ 1 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 $ 1. -h for help"; exit 1 ;;

*) BREAK ;;

ESAC

DONE

Echo "OPT_F IS $ OPT_F"

Echo "OPT_L IS $ OPT_L"

Echo "First Arg IS $ 1"

Echo "2nd Arg IS $ 2"

You can run this script like this:

cmdparser -l hello -f - -somefile1 somefile2

The result of returning is:

OPT_F IS 1

OPT_L IS Hello

First arg is -somefile1

2nd arg is somefile2

How is this script work? The script is first compared in all input command line parameters, comparing the input parameters to the CASE expression, set a variable if the match is matched and the parameter is removed. According to UNIX systems, the first input should be a parameter containing minus.

/ ******************************************** /

Example

General programming step

Now let's discuss the general steps to write a script. Any excellent script should have help and input parameters. And write a fake script (framework.sh), which contains the framework structure that most scripts need, is a very good idea. At this time, we only need to execute the copy command when writing a new script:

CP Framework.sh Myscript

Then insert your own function.

Let us look at two examples:

Binary to decimal conversion

The script B2D converts the binary number (such as 1101) into the corresponding decimal number. This is also an example of mathematical operation with an expr command:

#! / bin / sh

# vim: set sw = 4 Ts = 4 et:

Help ()

{

Cat

B2H - Convert Binary to Decimal

USAGE: B2H [-H] binarynum

Options: -h Help Text

EXAMPLE: B2H 111010

Will Return 58

Help

EXIT 0

}

Error ()

{

#print an error and exit

Echo "$ 1"

EXIT 1

}

Lastchar ()

{

# RETURN THE Last Character of A String In $ RAL

IF [-z "$ 1"]; then

# EMPTY STRING

Rval = ""

Return

Fi

# wc puts some space behind the output this is why we need sed:

Numofchar = `echo -n" $ 1 "| wc -c | sed 's /// g'`

# Now cut out the last charrval = `echo -n" $ 1 "| cut -b $ numofchar`

}

Chop ()

{

# Remove The Last Character in String and Return It in $ RALAL IN

IF [-z "$ 1"]; then

# EMPTY STRING

Rval = ""

Return

Fi

# wc puts some space behind the output this is why we need sed:

Numofchar = `echo -n" $ 1 "| wc -c | sed 's /// g'`

IF [$ NumOfchar "=" 1 "]; then

# Only One Char in String

Rval = ""

Return

Fi

Numofcharminus1 = `expr $ numofchar" - "1`

# Now cut all but the last char:

Rval = `echo -n" $ 1 "| cut -b 0 - $ {numofcharminus1}`

}

While [-n "$ 1"]; do

Case $ 1 in

-H) Help; shift 1 ;; # function help is called

-) SHIFT; Break ;; # end of options

- *) Error "Error: No Such Option $ 1. -h for help" ;;

*) BREAK ;;

ESAC

DONE

# The main program

SUM = 0

Weight = 1

# One arg must be given:

[-z "$ 1"] && Help

Binnum = "$ 1"

Binnumorig = "$ 1"

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 this script is to use decimal and binary value (1, 2, 4, 8, 16, ..), such as binary "10" can be converted into Ten-based:

0 * 1 1 * 2 = 2

In order to get a single binary number, we use the lastchar function. This function uses the WC-C calculating the number of characters and then uses the CUT command to take out a character. The function of the CHOP function is to remove the last character.

File cycle program

Perhaps you want to save all sent messages to one of the people in a file, but after a few months, this file may become great to make the accesses for the file slow down. The following script RotateFile can solve this problem. This script can rename the mail save file (assuming to Outmail) is Outmail.1, and it has become Outmail.2, etc. for Outmail.1, etc. ... #! / Bin / sh

# vim: set sw = 4 Ts = 4 et:

Ver = "0.1"

Help ()

{

Cat

RotateFile - Rotate the file name

USAGE: ROTATEFILE [-H] FileName

Options: -h Help Text

Example: RotateFile Out

This Will E.G Rename Out.2 to out.3, out to out.2, out to out.1

AND CREATE AN EMPTY OUT-FILE

THE MAX NUMBER IS 10

Version $ VER

Help

EXIT 0

}

Error ()

{

Echo "$ 1"

EXIT 1

}

While [-n "$ 1"]; do

Case $ 1 in

-H) HELP; Shift 1 ;;

-) BREAK ;;

- *) Echo "Error: No Such Option $ 1. -h for help"; exit 1 ;;

*) BREAK ;;

ESAC

DONE

# input check:

IF [-z "$ 1"]; then

Error "error: you must specify a file, use -h for help"

Fi

FILEN = "$ 1"

# 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

Fi

DONE

# Rename The Original File:

IF [-f "$ filen"]; then

Echo "MV $ Filen $ Filen.1"

MV $ Filen $ Filen.1

Fi

Echo Touch $ Filen

Touch $ Filen

How is this script work? After the user provides a file name, we will perform a cycle of 9 to 1. The file 9 is named 10, and the file 8 is renamed 9 and so on. After the loop is complete, we name the original file to file 1 to establish a empty file with the same name as the original file.

debugging

The easiest debug command is of course using an echo command. You can print any variable values ​​using Echo in any place where you doubt. This is also the cause of 80% of the time to debug the procedure. The advantage of the shell program does not need to recompile, and insert an echo command does not need much time.

The shell also has a real debug mode. If there is an error in the script "STRANGEScript", you can debug this:

SH -X StrangeScript

This will execute the script and display the value of all variables.

There is still a mode that doesn't need to perform scripts just check the syntax. It can be used like this:

sh -n your_script

This will return all syntax errors.

转载请注明原文地址:https://www.9cbs.com/read-92212.html

New Post(0)