Use Bash to write a Linux Shell script-7. Composite command

Source: Internet
Author: User
Tags error status code

Reprinted from: http://blog.csdn.net/fox_lht/archive/2010/09/20/5897336.aspx

7. Compound commands

Except for the simplest script, you rarely want to execute every command. Executing a group of commands or repeating a group of commands several times is more helpful than executing a single command. Composite commands encapsulate commands in a group of other commands.

For readability, the encapsulated command uses the indent format to make the code of the compound command clear and easy to read. The Administrator once complained that my indentation is less than the standard indentation (I must use a ruler to measure on the screen to determine this). I don't think this is a problem, but he said, when 0 is input, its program crashes.

Composite commands are always composed of two commands. The command Terminator is the reverse spelling order of the command. It is like using parentheses to enclose the command. For example, the mysterious command esac is actually the ending character of the composite Command case.

Command status code

Each Linux Command returns a status code (exit), which is a 0 ~ A number between 255 to indicate the problem encountered by the command. If the return value of the status code is 0, the command is successfully run, and other status codes indicate an error.

The status code is included in the variable "$? .

$ Unzip no_file.zip

Unzip: cannot find no_file.zip, no_file.zip.zip or no_file.zip.ZIP.

$ Printf "% d \ n" "$ ?"

9

The unzip command cannot find the file to be decompressed. The returned status code is 9.

Unofficial Linux practices use Status Code 127 and are smaller than standard error codes. For example, if ls returns status code 9, it indicates "bad file number ". Complete error codes are listed in Appendix D: "error code.

If the command is interrupted by a signal, Bash returns status code 128 with the upper-mail number. Finally, the user's error code should be greater than 191, and the error code returned by Bash is 63. The signal code is listed in Appendix E: signal.

If test! -X "$ who"; then

Printf "$ SCRIPT: $ LINENO: the command $ who is not available-" \

"Aborting \ n"> & 2

Exit 192

Fi

Generally, most Linux commands simply return 1 or 0, indicating that the operation fails or succeeds. This may be all the information required by your script. Any special error information is displayed on the standard output.

$ Ls po_1473.txt

Po_1473.txt

$ Printf "% d \ n" $?

0

$ Ls no_file

No_file not found

$ Printf "% d \ n" $?

1

The status code is different from the true value returned by the let Command (discussed in chapter 6). This section is called a logical expression. In the let Command, the value of false is 0, which is in line with the computer language's habits. However, if the status code is 0, it indicates success rather than failure.

$ Let "RESULT = 1> 0"

$ Printf "% d \ n" "$ RESULT" $?

1 0

$ Test 1-gt 0

$ Printf "% d \ n" $?

0

The let Command assigns 1 to RESULT, indicating that 1 is greater than 0. The test command returns status code 0, indicating that the command is successfully run. The let command returns the status code 0, indicating that the let Command is successfully compared.

These opposite codes and habits may cause errors, which are difficult to debug. Bash has two built-in commands: true and false. These are returned status codes, not the true values of the let Command.

$ True

$ Printf "% d \ n" "$ ?"

0

$ False

$ Printf "% d \ n" "$ ?"

1

The true command assigns a success status code (0 ). Fasle assigns an error status code (1 ).

A little messy, right?

If you want to save the successful status of the logical comparison, you 'd better use the test command. Most shells use status codes instead of true values.

In the pipeline, run several commands at a time. The status code returned from the MPs queue is the status code of the last command. In the following example, the status code of the wc command rather than the ls command is displayed.

$ Ls badfile.txt | wc-l

Ls: badfile.txt: No such file or directory

0

$ Printf "% d \ n" "$ ?"

0

Although ls reports an error, the status code returned by the MPs queue is successful because the wc command runs successfully.

Bash also defines an array called PIPESTATUS, which contains the individual status of each command in the running pipeline.

$ Ls badfile.txt | wc-l

Ls: badfile.txt: No such file or directory

0

$ Printf "% d \ n" "$ {PIPESTATUS [0]}" "$ {PIPESTATUS [1]}"

1 0

$? Is the alias of the last value of the pipestatus array.

A command or pipeline can be "!" Perform a reverse operation on the status. If the return value is 0, the return value is 1. If the return value is greater than 0, the return value is 0.

If command

Run the if command to select one or more operations.

Generally, if and test commands are used together.

NUM_ORDERS = 'LS-1 | wc-l'

If ["$ NUM_ORDERS"-lt "$ CUTOFF"]; then

Printf "% s \ n" "Too few orders... try running again later"

Exit 192

Fi

In this example, the files in the current directory are counted. If there are not enough files, a message is displayed. Otherwise, the fi command ends.

The semicolon before the then command is required. Although it works with the if command, it is still a separate command, so it must be separated by a semicolon.

The if command can also have a branch of the else command, which can be run when the condition fails.

NUM_ORDERS = 'LS-1 | wc-l'

If ["$ NUM_ORDERS"-lt "$ CUTOFF"]; then

Printf "% s \ n" "Too few orders... but will process them anyway"

Else

Printf "% s \ n" "Starting to process the orders"

Fi

The if command can be nested inside the if command.

NUM_ORDERS = 'LS-1 | wc-l'

If [[$ NUM_ORDERS-lt $ TOOFEW]; then

Printf "% s \ n" "Too few orders... but will process them anyway"

Else

If [[$ NUM_ORDERS-gt $ tooders]; then

Printf "% s \ n" "There are waiting orders. Processing may take a long time"

Else

Printf "% s \ n" "Starting to process the orders"

Fi

Fi

If cannot be cross-nested, that is, if must be completely in the external if command.

To implement multiple branches, the if command can have elif branches. The elif command is short for else if, which can reduce unnecessary nesting. You can add an else command at the end of the elif command, which is executed when no conditions are in progress. With this knowledge, you can rewrite the above example:

NUM_ORDERS = 'LS-1 | wc-l'

If ["$ NUM_ORDERS"-lt "$ TOOFEW"]; then

Printf "% s \ n" "Too few orders... but will process them anyway"

Elif ["$ NUM_ORDERS"-gt "$ tooders"]; then

Printf "% s \ n" "There are waiting orders. Processing may take a long time"

Else

Printf "% s \ n" "Starting to process the orders"

Fi

The if command can not be used with the test command. It can execute related tasks according to the status code returned by the command.

If rm "$ TEMPFILE"; then

Printf "% s \ n" "$ SCRIPT: temp file deleted"

Else

Printf "% s-status code % d \ n "\

"$ SCRIPT: $ LINENO: unable to delete temp file" $? 2> &

Fi

Embedding complex commands in the if Command makes the script language hard to read and debug. You should avoid doing so. In this example, if the rm command fails to run, it first displays its own prompt information, and then displays the information in the script. Although variables can also be declared in the if command, it is difficult to determine that the variable exists and that does not exist.

Case command

Use the case command to test template matching. If the value matches a template, run the corresponding command. Variables are tested one by one.

Unlike the elif command, the test status code comes from the same command, and the case test variable value. If the value of the test string is used, the case command is better than the elif command.

Each case branch must be separated by a semicolon. Without a semicolon, Bash executes the next branch and reports an error.

Printf "% s->" 1 = delete, 2 = archive. Please choose one"

Read REPLY

Case "$ REPLY" in

1) rm "$ TEMPFILE ";;

2) mv "$ TEMPFILE" "$ TEMPFILE. old ";;

*) Printf "% s \ n" "$ REPLY was not one of the choices ";;

Esac

Asterisk indicates all tasks that do not match the template conditions. Although this is optional, a good design should have such a statement, even if it is an empty statement.

The template matching rules follow the globbing rules. For details, refer to the previous chapter. For example, a vertical bar can separate multiple templates.

Case is different from other computer languages and will not be followed. If one condition is selected, other cases are not executed.

While Loop

You can execute multiple commands.

The while command is executed in the Command Group enclosed in the while command according to the test conditions. If the command fails, the command group in the while command is not executed.

Printf "% s \ n" "Enter the names of companies or type control-d"

While read-p "Company ?" COMPANY; do

If test-f then orders_$company.txt "; then

Printf "% s \ n" "There is an order file from this company"

Else

Printf "% s \ n" "There are no order files from this company"

Fi

Done

The while command ends with the done command. It's not a command like elihw you might think.

If you use the "true" command as the test condition, the while command loops infinitely, because true always returns success, and the loop will undoubtedly continue.

Printf "% s \ n" "Enter the names of companies or type quit"

While true; do

Read-p "Company ?" COMPANY

If ["$ COMPANY" = "quit"]; then

Break

Elif test-f then orders_$company.txt "; then

Printf "% s \ n" "There is an order file from this company"

Else

Printf "% s \ n" "There are no order files from this company"

Fi

Done

You can use the break command to stop a while loop in advance. After the break command is reached, Bash will jump out of the loop and execute the First Command outside the loop.

The break can be followed by a number, indicating the number of loops that have exceeded. For example:

Break 2

Jump out of a 2-layer loop.

The corresponding to break is the continue command, which ignores the subsequent commands and starts from scratch. The continue command can be followed by a number to indicate the loop to which layer to jump.

Until Loop

The until loop command corresponds to the while loop. The until loop stops executing the Command Group in the until statement until the test condition is successful. The other commands are basically the same as the until command. It is equivalent to while !.

Until test-f "$ INVOICE_FILE"; do

Printf "% s \ n" "Waiting for the invoice file to arrive ..."

Sleep 30

Done

When false and until are used together, an infinite loop can be created. The break and continue commands can also be used in the until loop command.

For Loop command

The standard burn for in loop is the variable file here. The for command puts a series of values into the variables and then executes the included commands.

For FILE_PREFIX in order invoice purchase_order; do

If test-f implements file_prefix1_1__vendor1.txt "; then

Printf "% s \ n" "There is a $ FILE_PREFIX file from vendor 1 ..."

Fi

Done

If there are no parameters after in, for loops in the parameters in the shell script.

The break and continue commands can be used for a for loop.

Because of the features of other shells, the for loop is not universal.

Embedded let Command (((..)))

If the expression is 0, the let command returns status code 1. If the expression is not 0, the return value is 0. Like the test command, you can use a pair of square brackets to indicate that reading is easier. The let command also has a representation that is easier to read and uses double brackets.

The following example uses the for loop embedded let Command in list 7.1:

List 7.1

#! /Bin/bash

# Forloop. sh: Count from 1 to 9

For (COUNTER = 1; COUNTER <10; COUNTER ++); do

Printf "The counter is now % d \ n" "$ COUNTER"

Done

Exit 0

When the loop starts, execute the first expression in the double brackets, execute the third expression at the beginning of each loop, and check the second expression. When the second expression returns false, the loop ends.

$ Bash forloop. sh

The counter is now 1

The counter is now 2

The counter is now 3

The counter is now 4

The counter is now 5

The counter is now 6

The counter is now 7

The counter is now 8

The counter is now 9

Command Group ({..})

The command can be combined into a group using braces.

Ls-1 | {

While read FILE; do

Echo "$ FILE"

Done

}

In this instance, the result of the ls command becomes the input of the Group Command.

$ Test-f orders.txt & {ls-l orders.txt; rm orders.txt ;}\

| Printf "no such file"

If the orders.txt file exists, the file is displayed and then deleted. Otherwise, "no such file" is displayed ". The commands in braces must be separated by semicolons.

Commands can also be grouped using sub-shells, which will be discussed in chapter 9.

Report. bash: report formatting

Report. bash is a script program used to create reports for sales numbers. The sales digital file consists of the product name, the number of local sales, and the number of foreign sales. For example, report. bash puts the following report

Binders 1024 576

Pencils 472 235

Rules 311 797

Stencils 846 621

Convert

Report created on Thu Aug 22 18:27:07 EDT 2002 by kburtch

Sales Report

Product Country Foreign Total Average

----------

Binders 1024 576 1600 800

Pencils 472 235 707 353

Rules 311 797 1108 554

Stencils 846 621 1467 733

----------

Total number of products: 4

End of report

List 7.2 report. bash

! /Bin/bash

#

# Report. bash: simple report formatter

#

# Ken O. Burtch

# CVS: $ Header $

# The report is read from DATA_FILE. It shoshould contain

# The following columns:

#

# Column 1: PRODUCT = Product name

# Column 2: CSALES = Country Sales

# Column 3: FSALES = Foreign Sales

#

# The script will format the data into columns, adding total and

# Average sales per item as well as a item count at the end of

# Report.

# Some Linux systems use USER instead of LOGNAME

If [-z "$ LOGNAME"]; then # No login name?

Declare-rx LOGNAME = "$ USER" # probably in USER

Fi

Shopt-s-o nounset

# Global Declarations

Declare-rx SCRIPT =$ {0 ##*/} # SCRIPT is the name of this script

Declare-rx data_file1_report.txt "# this is raw data for the report

Declare-I ITEMS = 0 # number of report items

Declare-I LINE_TOTAL = 0 # line totals

Declare-I LINE_AVG = 0 # line average

Declare PRODUCT # product name from data file

Declare-I CSALES # country sales from data file

Declare-I FSALES # foreign sales from data file

Declare-rx REPORT_NAME = "Sales Report" # report title

# Sanity Checks

If test! -R "$ DATA_FILE"; then

Printf "$ SCRIPT: the report file is missing-aborting \ n"> & 2

Exit 192

Fi

# Generate the report

Printf "Report created on % s by % s \ n" "'date'" "$ LOGNAME"

Printf "\ n"

Printf "% s \ n" "$ REPORT_NAME"

Printf "\ n"

Printf "%-12 s % 12 s % 12 s % 12 s % 12s \ n" "Product" "Country" "Foreign" "Total" "Average"

Printf "%-12 s % 12 s % 12 s % 12 s % 12s \ n" "--" -- "" --"

{While read product csales fsales; do

Let "ITEMS + = 1"

LINE_TOTAL = "CSALES + FSALES"

LINE_AVG = "(CSALES + FSALES)/2"

Printf "%-12 s % 12d % 12d % 12d % 12d \ n" "$ PRODUCT" "$ CSALES" "$ FSALES "\

"$ LINE_TOTAL" "$ LINE_AVG"

Done} <$ DATA_FILE

# Print report trailer

Printf "%-12 s % 12 s % 12 s % 12 s % 12s \ n" "--" -- "" --"

Printf "Total number of products: % d \ n" "$ ITEMS"

Printf "\ n"

Printf "End of report \ n"

Exit 0

Related Article

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.