Bourne tutorial



Yüklə 478,18 Kb.
Pdf görüntüsü
səhifə17/20
tarix08.10.2017
ölçüsü478,18 Kb.
#3721
1   ...   12   13   14   15   16   17   18   19   20

for i in 1 2 3 4 5 6 7 8 9 10

do

echo $i



done

prints out ten lines, with a number on each line. The variable "i" is assigned the values of each of the

ten numbers. This could also be written as:

numbers="1 2 3 4 5 6 7 8 9 10"

for i in $numbers

do

echo $i



done

Change


for i in $numbers

to

for i in $numbers $numbers



and the script will output twice as many lines. The variables on the are evaluated as all variables are.

Change


for i in $numbers

to

for i in "$numbers"



and it will print out one line with all ten numbers, because there is only one argument after the "in"

command. There are many ways to specify the list of arguments in the "for" command. You can use a

Clever Thing to modify two variables in a loop, by combining the "for" command with the "set"

command:


for args in "a A" "b B" "c C"

do

set $args



echo lower case is $1, upper case is $2

done


Of course you can use back-quotes to use the output of a command as the creator of the list:

for i in `ls file*`

The line-at-a-time information is lost, as all newline characters are removed. Therefore you cannot

easily use the "set" command to modify two or more variables at a time. If you want to change multiple

arguments from a file, you either have to use the "while read" sequence I described earlier, or read a

variable, and split one variable into multiples using a command like "tr" to convert some character into

spaces, and then using "set" to change several variables at once:

#!/bin/sh

# read the /etc/password file

Bourne Shell Tutorial

http://www.grymoire.com/Unix/Sh.html

48 of 66


11/21/2011 12:03 PM


# use `cat /etc/passwd`, but spaces are treated like new lines

# therefore, change spaces into _

for i in `tr ' ' '_' 

do

set `echo $i | tr ':' ' '`



echo user: $1, UID: $3, Home Directory: $6

done


You can use standard input to get the list of values for the variable:

for a in `cat`

Lastly, you can combine variables, constants, and program executions:

for i in BEGIN $a "$b $c" `cat file` END

do

echo i is $i



done

Of course any variable besides "i" will work. You don't have to specify the list of values after the "in"

command. If not specified, the positional arguments are used. To illustrate, if you had a script called

"script1" and executed

script1 a b c

and wanted to count the number of words in each file, then you could use

#!/bin/sh

echo $1 has `wc -l <$1` words

echo $2 has `wc -l <$2` words

echo $3 has `wc -l <$3` words

Another way to do the same is as follows:

#!/bin/sh

for file

do

echo $file has `wc -l <$file` words



done

Case - Checking multiple cases

The case statement functions like a complex "if" statement, with multiple clauses. The template is:

case word in pattern | pattern ) list;; esac

Let's suppose you wanted to get a yes or no answer to a question. An example is:

echo answer yes or no

read word

case $word in

yes | YES )

echo you answered yes

Bourne Shell Tutorial

http://www.grymoire.com/Unix/Sh.html

49 of 66

11/21/2011 12:03 PM




;;

no | NO )

echo you answered no

;;

esac



The "case" statement works on patterns, like filename matching. The above example won't let you

specify a single character. You must type the full word. If you type "Yes," it will not recognize it as a

yes because the first letter is upper case, and the other letters are lower case. There is a fix. The

patterns are filename patterns. Therefore you can modify the above script to be:

echo answer yes or no

read word

case $word in

[Yy]* )


echo you answered yes

;;

[Nn]* )



echo you answered no

;;

* )



echo you did not say yes or no;;

esac


You will notice the last test, containing an asterisk. This is the standard method of specifying a default

condition for the "case" statement. The last pattern in this case will always match.

There can only be one word between "case" and "in." The following is a syntax error:

case a b c in

To prevent this error, especially when the item you are checking comes from another program, use a

variable.

#!/bin/sh

arg="a b c"

case $arg in

[aAbBcC] ) echo this never matches;;

"a b c") echo this will match;;

esac


You could put quotes around "$arg," but this is not needed on my Sun system. Perhaps it is a good idea,

in case some older version of the Bourne shell has a bug. You will also notice the doubled up

semicolon. This is required. Consider this fragment:

case $arg in

a ) echo yes; b ) echo no;;

esac


The "b" looks like a command, as far as the shell knows, followed by an illegal ")." The ";;" is needed

to tell the shell the next word found is a pattern, not a command. By the way, the following is legal:

case $arg in

esac


It doesn't do anything, but the shell accepts this syntax.

Bourne Shell Tutorial

http://www.grymoire.com/Unix/Sh.html

50 of 66


11/21/2011 12:03 PM


Break and continue

The "for" and "while" commands execute each portion of code more than once. If you want to test a

condition, and exit from this loop, you can. You can control this by using the "break" or "continue"

commands. "Break" causes the control to exit the "for" or "while" statement. The "continue" statement

causes the loop to immediately start the next loop. Earlier, I used a "case" statement to check if the

input is a yes or no. If neither, an error occurs. If you want to wait until you have a proper answer, the

"break" statement can be used:

while :


do

echo "Type yes or no"

read answer

case "$answer" in

[yYnN]*) break;;

ecas


done

Notice I used the null command ":" instead of "/bin/true."" Both have the same function, but the null

command is built into the shell.

The "continue" command causes the "for" or "while" command to go to the next loop immediately The

following loop only prints the odd numbers:

for number in 1 2 3 4 5 6 7 8

do

case "$number" in



2|4|6|8) continue ;;

esac


echo $number

done


The, "for" and "while" commands can be nested. Which loops do the the "break" and "continue"

commands operate on? They work on the innermost loop, but you can override this. If you place a

number after the command, the number determines the depth of the loop. Take the following:

for number in 1 2 3 4 5 6

do

for letter in a b c d e f g



do

case $number in

3) break

esac


echo $number $letter

done


done

This will print every combination of letters and numbers, except it will not print any line with the

number "3." However, change the break to be "break 2," and the script will only print only

combinations that contain 1 or 2.

Bourne Shell Tutorial

http://www.grymoire.com/Unix/Sh.html

51 of 66

11/21/2011 12:03 PM




Yüklə 478,18 Kb.

Dostları ilə paylaş:
1   ...   12   13   14   15   16   17   18   19   20




Verilənlər bazası müəlliflik hüququ ilə müdafiə olunur ©www.genderi.org 2024
rəhbərliyinə müraciət

    Ana səhifə