苏泊尔电压力锅的食谱:Shell 中大括号(curly brackets)的含义

来源:百度文库 编辑:九乡新闻网 时间:2024/04/29 06:05:24
在 Shell 脚本中经常见到类似 CMD=${0}、RMAN_LOG_FILE=${0}.out 带大括号的语法,它是什么意思?可去参考 Stephen G. Kochan 《Unix Shell Programming, 3rd Edition》一书 15.11 节 Arrays. 其中的语句可直接在 Shell 命令符下去实验。

Arrays

The Korn shell and Bash provide alimited array capability (arrays are not a part of the POSIX standard shell).Bash arrays may contain an unlimited number of elements (subject to memorylimitations); Korn shell arrays are limited to 4096 elements. Array indexing inboth shells starts at zero. An array element is accessed with a subscript, which is an integer-valued expressionenclosed inside a pair of brackets. You don't declare the maximum size of ashell array; you simply assign values to elements as you need them. The valuesthat you can assign are the same as for ordinary variables.

$ arr[O]=hello

$ arr[1]="some text"

$ arr[2]=/users/steve/memos

$

To retrieve an element from an array, you write the array namefollowed by the element number, enclosed inside a pair of brackets as before.The entire construct must be enclosed inside a pair of curly braces, which isthen preceded by a dollar sign.

$ echo ${array[0]}

hello

$ echo ${array[1]}

some text

$ echo ${array[2]}

/users/steve/memos

$ echo $array

hello

$

As you can see from the preceding example, if no subscript isspecified, element zero is used.

If you forget the curly braces when performing thesubstitution, here's what happens:

$ echo $array[1]

hello[1]

$

In the preceding example, the value of array issubstituted (hello—the value inside array[0]) and thenechoed along with [1]. (Note that because the shell doesfilename substitution after variable substitution, the shell would attempt tomatch the pattern hello[1] against the files in your currentdirectory.)

The construct [*] can be usedas a subscript to substitute all the elements of the array on the command line,with each element delimited by a single space character.

$ echo ${array[*]}

hello some text /users/steve/memos

$

The construct ${#array[*]} can be used to substitute the numberof elements in the array array.

$ echo ${#array[*]}

3

$

Note that the number reported here is the actual number ofvalues stored inside the array, not the largest subscript used to store anelement inside the array.

$ array[10]=foo

$ echo ${array[*]} Display all elements

hello some text /users/steve/memos foo

$ echo ${#array[*]} Number of elements

4

$

You can declare an array of integers to the shell simply bygiving the array name to typeset -i:

typeset -i data

Integer calculations can be performed on array elements usingthe ((...)) construct:

$ typeset -i array

$ array[0]=100

$ array[1]=50

$ (( array[2] = array[0] + array[1] ))

$ echo ${array[2]}

150

$ i=1

$ echo ${array[i]}

50

$ array[3]=array[0]+array[2]

$ echo ${array[3]}

250

$

Note that not only can you omit the dollar signs and the curlybraces when referencing array elements inside double parentheses, you also canomit them outside when the array is declared to be of integer type. Also notethat dollar signs are not needed before variables used in subscriptexpressions.

The following program, called reverse, reads in up to4096 lines from standard input and then writes them back out to standard outputin reverse order:

$ cat reverse

# read lines to array buf



typeset -i line=0



while (( line < 4096 )) && read buf[line]

do

(( line = line + 1 ))

done



# now print the lines in reverse order



while (( line > 0 )) do

(( line = line - 1 ))

echo "${buf[line]}"

done



$ reverse

line one

line two

line three

Ctrl+d

line three

line two

line one

$

The first while loop executes as long as 4096 or fewerlines have been read and there is more data to be read from standard input(recall the && described at the end of Chapter 8, "Decisions, Decisions").

The following function, cdh, changes the current directory like cdbut uses an array to keep a history of previous directories. It allows the userto list the directory history and change back to any directory in it:

$ cat cdh

CDHIST[0]=$PWD # initialize CDHIST[0]



cdh ()

{

typeset –i cdlen i

if [ $# -eq 0 ] # default to HOME with no arguments

then

set -- $HOME

fi



cdlen=${#CDHIST[*]} # number of elements in CDHIST



case "$@" in

-l) # print directory list

i=0

while ((i < cdlen))

do

printf "%3d %s\n" $i ${CDHIST[i]}

((i = i + 1))

done

return ;;

-[0-9]|-[0-9][0-9]) # cd to dir in list

i=${1#-} # remove leading '-'

cd ${CDHIST[i]} ;;

*) # cd to new dir

cd $@ ;;

esac



CDHIST[cdlen]=$PWD

}

$

The CDHIST array stores each directory visited bycdh, and the first element, CDHIST[0], is initialized with thecurrent directory when the cdh file is run:

$ pwd

/users/pat

$ . cdh Define cdh function

$ cdh /tmp

$ cdh –l

0 /users/pat

1 /tmp

$

When the cdh file was run, CDHIST[0] wasassigned /users/pat, and the cdh function was defined; whencdh /tmp was executed, cdlen was assigned the number ofelements in CDHIST (one), and CDHIST[1] was assigned/tmp. The cdh –l caused printf to display eachelement of CDHIST (on this invocation, cdlen was set to 2,because elements 0 and 1 of CDHIST contained data).

Note that the if statement at the beginning of thefunction sets $1 to $HOME if no arguments are passed. Let'stry that out:

$ cdh

$ pwd

/users/pat

$ cdh –l

0 /users/pat

1 /tmp

2 /users/pat

$

Well, it worked, but now /users/pat shows up twice inthe list. One of the exercises at the end of this chapter asks you to remedythis.

Okay, the most useful feature of cdh is then option, which causes it to change thecurrent directory to the one specified in the list:

$ cdh /usr/spool/uucppublic

$ cdh –l

0 /users/pat

1 /tmp

2 /users/pat

3 /usr/spool/uucppublic

$ cdh –1

$ pwd

/tmp

$ cdh –3

$ pwd

/usr/spool/uucppublic

$

We can make cdh replace our cd command byusing the fact that alias lookup is performed before built-in commands areexecuted. So if we create a cd alias to cdh, we can have anenhanced cd. In that case, we have to quote every use of cd inthe cdh function to prevent recursion:

$ cat cdh

CDHIST[0]=$PWD # initialize CDHIST[0]

alias cd=cdh



cdh ()

{

typeset –i cdlen i

if [ $# -eq 0 ] # default to HOME with no arguments

then

set -- $HOME

fi



cdlen=${#CDHIST[*]} # number of elements in CDHIST



case "$@" in

-l) # print directory list

i=0

while ((i < cdlen))

do

printf "%3d %s\n" $i ${CDHIST[i]}

((i = i + 1))

done

return ;;

-[0-9]|-[0-9][0-9]) # cd to dir in list

i=${1#-} # remove leading '-'

'cd' ${CDHIST[i]} ;;

*) # cd to new dir

'cd' $@ ;;

esac



CDHIST[cdlen]=$PWD

}

$ . cdh Define cdh function and cd alias

$ cd /tmp

$ cd –l

0 /users/pat

1 /tmp

$ cd /usr/spool

$ cd –l

0 /users/pat

1 /tmp

2 /usr/spool

$

Table 15.3 summarizesthe various array constructs in the Korn shell and Bash.

Table 15.3. Array Constructs

Construct

Meaning

${array[i]}

Substitute value of element i

$array

Substitute value of first element (array[0])

${array[*]}

Substitute value of all elements

${#array[*]}

Substitute number of elements

array[i]=val

Store val into array[i]