Unix/Linux shell脚本编程学习--Shell Script II

Shell Script II

10.Shell echo命令

  1. echo "OK!\n”   #显示换行
  2. echo "It is a test"

echo无拼接字符时后一般可以不使用”引号”,从上面可看出,双引号可有可无,单引号主要用在原样输出中。

显示结果重定向保存至文件:

  1. vim myfile 创建文件
  2. echo "It is a test" > myfile
  3. cat myfile 查看文件内容

若需要原样输出字符串(不进行转义),请使用单引号。例如:

复制纯文本新窗口

  1. echo ‘$name\"‘

11.shell printf命令:格式化输出语句

printf 命令用于格式化输出, 是echo命令的增强版。printf 不像 echo 那样会自动换行,必须显式添加换行符(\n)。

  1. $printf "Hello, Shell\n"
  1. # format-string为双引号
  2. $ printf "%d %s\n" 1 "abc"
  3. 1 abc
  4. # 单引号与双引号效果一样
  5. $ printf ‘%d %s\n‘ 1 "abc"
  6. 1 abc
  7. # 没有引号也可以输出
  8. $ printf %s abcdef
  9. abcdef
  10. # 格式只指定了一个参数,但多出的参数仍然会按照该格式输出,format-string 被重用
  11. $ printf %s abc def
  12. abcdef
  13. $ printf "%s\n" abc def
  14. abc
  15. def
  16. $ printf "%s %s %s\n" a b c d e f g h i j
  17. a b c
  18. d e f
  19. g h i
  20. j
  21. # 如果没有 arguments,那么 %s 用NULL代替,%d 用 0 代替
  22. $ printf "%s and %d \n"
  23. and 0
  24. # 如果以 %d 的格式来显示字符串,那么会有警告,提示无效的数字,此时默认置为 0
  25. $ printf "The first program always prints‘%s,%d\n‘" Hello Shell
  26. -bash: printf: Shell: invalid number
  27. The first program always prints ‘Hello,0‘
  28. $

12.Shell if else语句:

Shell 有三种 if ... else 语句:

  • if ... fi 语句;
  • if ... else ... fi 语句;
  • if ... elif ... else ... fi 语句。

 if ... else ... fi 语句

  1. if [ $a == $b ]
  2. then
  3. echo "a is equal to b"
  4. else
  5. echo "a is not equal to b"
  6. fi

 if ... elif ... fi 语句

  1. if [ $a == $b ]
  2. then
  3. echo "a is equal to b"
  4. elif [ $a -gt $b ]
  5. then
  6. echo "a is greater than b"
  7. elif [ $a -lt $b ]
  8. then
  9. echo "a is less than b"
  10. else
  11. echo "None of the condition met"
  12. fi

if ... else 语句也可以写成一行,以命令的方式来运行,像这样:

复制纯文本新窗口

  1. if test $[2*3] -eq $[1+5]; then echo ‘The two numbers are equal!‘; fi;

if ... else 语句也经常与 test 命令结合使用,如下所示:

复制纯文本新窗口

  1. num1=$[2*3]
  2. num2=$[1+5]
  3. if test $[num1] -eq $[num2]
  4. then
  5. echo ‘The two numbers are equal!‘
  6. else
  7. echo ‘The two numbers are not equal!‘
  8. fi

13.Shell case esac语句

case 语句匹配一个值或一个模式,如果匹配成功,执行相匹配的命令。case语句格式如下:

  1. read aNum
  2. case $aNum in
  3. 1)  echo ‘You select 1‘
  4. ;;
  5. 2)  echo ‘You select 2‘
  6. ;;
  7. 3)  echo ‘You select 3‘
  8. ;;
  9. 4)  echo ‘You select 4‘
  10. ;;
  11. *)  echo ‘You do not select a number between 1 to 4‘
  12. ;;
  13. esac

case工作方式如上所示。取值后面必须为关键字 in,每一模式必须以右括号结束。取值可以为变量或常数。匹配发现取值符合某一模式后,其间所有命令开始执行直至 ;;。;; 与其他语言中的 break 类似,意思是跳到整个 case 语句的最后。

取值将检测匹配的每一个模式。一旦模式匹配,则执行完匹配模式相应命令后不再继续其他模式。如果无一匹配模式,使用星号 * 捕获该值,再执行后面的命令。

  1. option="${1}"
  2. case ${option} in
  3. -f) FILE="${2}"
  4. echo "File name is $FILE"
  5. ;;
  6. -d) DIR="${2}"
  7. echo "Dir name is $DIR"
  8. ;;
  9. *)
  10. echo "`basename ${0}`:usage: [-f file] | [-d directory]"
  11. exit 1 # Command to come out of the program with status 1
  12. ;;
  13. esac

14.Shell for循环

  1. for循环一般格式为:for 变量 in 列表
  2. do
  3. command1
  4. ...
  5. commandN
  6. done

例如,顺序输出当前列表中的数字:顺序输出字符串中的字符:

  1. for loop in 1 2 3 4 5 string qwerty
  2. do
  3. echo "The value is: $loop"
  4. done

显示主目录下以 .bash 开头的文件:

  1. #!/bin/bash
  2. for FILE in $HOME/.bash*
  3. do
  4. echo $FILE
  5. done

14.Shell while循环

while循环用于不断执行一系列命令,也用于从输入文件中读取数据;命令通常为测试条件。其格式为:

while command

do

Statement(s) to be executed if command is true

done

命令执行完毕,控制返回循环顶部,从头开始直至测试条件为假。

以下测试条件是:如果COUNTER小于5,那么返回 true。

  1. COUNTER=0
  2. while [ $COUNTER -lt 5 ]
  3. do
  4. COUNTER=‘expr $COUNTER+1‘
  5. echo $COUNTER
  6. done

while循环可用于读取键盘信息。下面的例子中,输入信息被设置为变量FILM,按<Ctrl-D>结束循环。

  1. echo ‘type <CTRL-D> to terminate‘
  2. echo -n ‘enter your most liked film: ‘
  3. while read FILM
  4. do
  5. echo "Yeah! great film the $FILM"
  6. done

15.Shell until循环

与 while 循环在处理方式上刚好相反, until 循环执行一系列命令直至条件为 true 时停止,循环格式为:

until command

do

Statement(s) to be executed until command is true

done

  1. a=0
  2. until [ ! $a -lt 10 ]
  3. do
  4. echo $a
  5. a=`expr $a + 1`
  6. done

command 一般为条件表达式,如果返回值为 false,则继续执行循环体内的语句,否则跳出循环。

16.Shell breakcontinue命令

break命令允许跳出所有循环(终止执行后面的所有循环)。

  1. while :
  2. do
  3. echo -n "Input a number between 1 to 5: "
  4. read aNum
  5. case $aNum in
  6. 1|2|3|4|5) echo "Your number is $aNum!"
  7. ;;
  8. *) echo "You do not select a number between 1 to 5, game is over!"
  9. break
  10. ;;
  11. esac
  12. done

在嵌套循环中,break n命令后面还可以跟一个整数,表示跳出第几层循环:

  1. for var1 in 1 2 3
  2. do
  3. for var2 in 0 5
  4. do
  5. if [ $var1 -eq 2 -a $var2 -eq 0 ]
  6. then
  7. break 2
  8. else
  9. echo "$var1 $var2"
  10. fi
  11. done
  12. done

如上,break 2 表示直接跳出外层循环。

continue命令与break命令类似,只有一点差别,它不会跳出所有循环,仅仅跳出当前循环。

  1. while :
  2. do
  3. echo -n "Input a number between 1 to 5: "
  4. read aNum
  5. case $aNum in
  6. 1|2|3|4|5) echo "Your number is $aNum!"
  7. ;;
  8. *) echo "You do not select a number between 1 to 5!"
  9. continue
  10. echo "Game is over!"
  11. ;;
  12. esac
  13. done

运行代码发现,当输入大于5的数字时,该例中的循环不会结束,语句

  1. echo "Game is over!"

永远不会被执行。

同样,continue 后面也可以跟一个数字,表示跳出第几层循环。

  1. NUMS="1 2 3 4 5 6 7"
  2. for NUM in $NUMS
  3. do
  4. Q=`expr $NUM % 2`
  5. if [ $Q -eq 0 ]
  6. then
  7. echo "Number is an even number!!"
  8. continue
  9. fi
  10. echo "Found odd number"
  11. done

17.Shell函数:Shell函数返回值、删除函数、在终端调用函数

Shell 函数的定义格式如下(关键字 function可以不加)

function function_name () {

list of commands

[ return value ]

}

调用函数只需要给出函数名,不需要加括号。

函数返回值在调用该函数后通过 $? 来获得。

#!/bin/bash

# Define your function here

funcWithReturn(){

echo -n "input a number now!:"  #加 -n 取消输出换行

read numb;

rn=`expr $numb + 2`

return $rn

}

funcWithReturn  #调用函数 无需带()

ret=$?      #使用¥?读取上面的函数返回值

echo "result of funcWithReturn is: $ret"

#函数嵌套:

nestedFunc(){

funcWithReturn    #函数内部调用其他函数 函数嵌套

printf %s\\n $?

}

nestedFunc

像删除变量一样,删除函数也可以使用 unset 命令,不过要加上 .f 选项

  1. $unset .f function_name

如果你希望直接从终端调用函数,可以将函数定义在主目录下的 .profile 文件,这样每次登录后,在命令提示符后面输入函数名字就可以立即调用。

18.Shell函数参数

在Shell中,调用函数时可以向其传递参数。在函数体内部,通过 $n 的形式来获取参数的值,例如,$1表示第一个参数,$2表示第二个参数...funWithParam(){

echo "参数个数 $# !"  # 参数个数

echo "传递给函数的所有参数:$*"  # 传递给函数的所有参数

echo "第一个参数 $1 !"

echo "第二个参数 $2 !"

echo "第十个参数 ${10} !"   #第十个以上的参数就需要带{}访问了

echo "第十一个参数 ${11} !"

}

#调用函数时,后面跟上参数的列表

funWithParam 1 2 3 4 5 6 7 8 9 34 73

注意,$10 不能获取第十个参数,获取第十个参数需要${10}。当n>=10时,需要使用${n}来获取参数。

特殊变量列表

变量

含义

$0

当前脚本的文件名

$n

传递给脚本或函数的参数( 命令行参数 )。n 是一个数字,表示第几个参数。

例如,第一个参数是$1,第二个参数是$2。

$#

传递给脚本或函数的参数个数。

$*

传递给脚本或函数的所有参数。

[email protected]

传递给脚本或函数的所有参数。

被双引号(" ")包含时,与 $* 稍有不同,下面将会讲到。

$?

上个命令的退出状态,或函数的返回值。

$$

当前Shell进程ID。对于 Shell 脚本,就是这些脚本所在的进程ID。

$* [email protected] 的区别:$* [email protected] 都表示传递给函数或脚本的所有参数,不被双引号(" ")包含时,都以"$1" "$2" … "$n" 的形式输出所有参数.

退出状态 : $?可以获取上一个命令的退出状态。大部分命令执行成功会返回 0,失败返回 1($? 也可以表示函数的返回值)

18.Shell输入输出重定向:Shell Here Document/dev/null文件

Unix 命令默认从标准输入设备(stdin)获取输入,将结果输出到标准输出设备(stdout)显示。一般情况下,标准输入设备就是键盘,标准输出设备就是终端,即显示器。

输出重定向:命令的输出不仅可以是显示器,还可以很容易的转移向到文件。语法:  $ command> file

  1. $ who > users     #who命令的输出信息定向到文件users

输出重定向会覆盖文件内容!

如果不希望文件内容被覆盖,可以使用 >> 追加到文件末尾:

$ echo line 2 >> users

$ cat users

输入重定向和输出重定向一样,Unix 命令也可以从文件获取输入,语法为:$command< file

这样,本来需要从键盘获取输入的命令会转移到文件读取内容。

注意:输出重定向是大于号(>),输入重定向是小于号(<)。

$ wc -l users      #计算 users 文件中的行数

也可以将输入重定向到 users 文件: $ wc -l < users

一般情况下,每个 Unix/Linux 命令运行时都会打开三个文件:

  • 标准输入文件(stdin):stdin的文件描述符为0,Unix程序默认从stdin读取数据。
  • 标准输出文件(stdout):stdout 的文件描述符为1,Unix程序默认向stdout输出数据。
  • 标准错误文件(stderr):stderr的文件描述符为2,Unix程序会向stderr流中写入错误信息。

默认情况下,command > file 将 stdout 重定向到 file,command < file 将stdin 重定向到 file。

如果希望 stderr 重定向到 file,可以这样写:

  1. $command 2 > file

如果希望 stderr 追加到 file 文件末尾,可以这样写:

  1. $command 2 >> file

2 表示标准错误文件(stderr)。

如果希望将 stdout 和 stderr 合并后重定向到 file,可以这样写:

  1. $command > file 2>&1     cal > f 2>&1

  1. $command >> file 2>&1

如果希望对 stdin 和 stdout 都重定向,可以这样写:

  1. $command < file1 >file2

command 命令将 stdin 重定向到 file1,将 stdout 重定向到 file2。

全部可用的重定向命令列表

命令

说明

command > file

将输出重定向到 file。

command < file

将输入重定向到 file。

command >> file

将输出以追加的方式重定向到 file。

n > file

将文件描述符为 n 的文件重定向到 file。

n >> file

将文件描述符为 n 的文件以追加的方式重定向到 file。

n >& m

将输出文件 m 和 n 合并。

n <& m

将输入文件 m 和 n 合并。

<< tag

将开始标记 tag 和结束标记 tag 之间的内容作为输入。

19.Here Document 目前没有统一的翻译,这里暂译为嵌入文档Here Document Shell 中的一种特殊的重定向方式,它的基本的形式如下:

  1. command << delimiter
  2. document
  3. delimiter

它的作用是将两个 delimiter 之间的内容(document) 作为输入传递给 command。

注意:

  • 结尾的delimiter 一定要顶格写,前面不能有任何字符,后面也不能有任何字符,包括空格和 tab 缩进。
  • 开始的delimiter前后的空格会被忽略掉。

下面的例子,通过 wc -l 命令计算 document 的行数:

$wc -l << EOF

This is a simple lookup program

for good (and bad) restaurants

in Cape Town.

EOF

3

$

也可以 将 Here Document 用在脚本中,例如:

  1. #!/bin/bash
  2. cat << EOF
  3. This is a simple lookup program
  4. for good (and bad) restaurants
  5. in Cape Town.
  6. EOF

运行结果:

This is a simple lookup program

for good (and bad) restaurants

in Cape Town.

下面的脚本通过 vi 编辑器将 document 保存到 test.txt 文件:

  1. #!/bin/sh
  2. filename=test.txt
  3. vi $filename <<EndOfCommands
  4. i
  5. This file was created automatically from
  6. a shell script
  7. ^[
  8. ZZ
  9. EndOfCommands

运行脚本:

$ sh test.sh

Vim: Warning: Input is not from a terminal

$

打开 test.txt,可以看到下面的内容:

$ cat test.txt

This file was created automatically from

a shell script

$

/dev/null 文件

如果希望执行某个命令,但又不希望在屏幕上显示输出结果,那么可以将输出重定向到 /dev/null:

  1. $ command > /dev/null

/dev/null 是一个特殊的文件,写入到它的内容都会被丢弃;如果尝试从该文件读取内容,那么什么也读不到。但是 /dev/null 文件非常有用,将命令的输出重定向到它,会起到”禁止输出“的效果。

如果希望屏蔽 stdout 和 stderr,可以这样写:

  1. $ command > /dev/null 2>&1

20.Shell文件包含

像其他语言一样,Shell 也可以包含外部脚本,将外部脚本的内容合并到当前脚本。

Shell 中包含脚本可以使用:

  1. . filename

  1. source filename

两种方式的效果相同,简单起见,一般使用点号(.),但是注意点号(.)和文件名中间有一空格。

例如,创建两个脚本,一个是被调用脚本 subscript.sh,内容如下:

  1. url="http://see.xidian.edu.cn/cpp/view/2738.html"

一个是主文件 main.sh,内容如下:

  1. #!/bin/bash
  2. . ./subscript.sh
  3. echo $url

执行脚本:

$chomd +x main.sh

./main.sh

http://see.xidian.edu.cn/cpp/view/2738.html

$

注意:被包含脚本不需要有执行权限。

Shell Script II

10.Shell echo命令

  1. echo "OK!\n”   #显示换行
  2. echo "It is a test"

echo无拼接字符时后一般可以不使用”引号”,从上面可看出,双引号可有可无,单引号主要用在原样输出中。

显示结果重定向保存至文件:

  1. vim myfile 创建文件
  2. echo "It is a test" > myfile
  3. cat myfile 查看文件内容

若需要原样输出字符串(不进行转义),请使用单引号。例如:

复制纯文本新窗口

  1. echo ‘$name\"‘

11.shell printf命令:格式化输出语句

printf 命令用于格式化输出, 是echo命令的增强版。printf 不像 echo 那样会自动换行,必须显式添加换行符(\n)。

  1. $printf "Hello, Shell\n"
  1. # format-string为双引号
  2. $ printf "%d %s\n" 1 "abc"
  3. 1 abc
  4. # 单引号与双引号效果一样
  5. $ printf ‘%d %s\n‘ 1 "abc"
  6. 1 abc
  7. # 没有引号也可以输出
  8. $ printf %s abcdef
  9. abcdef
  10. # 格式只指定了一个参数,但多出的参数仍然会按照该格式输出,format-string 被重用
  11. $ printf %s abc def
  12. abcdef
  13. $ printf "%s\n" abc def
  14. abc
  15. def
  16. $ printf "%s %s %s\n" a b c d e f g h i j
  17. a b c
  18. d e f
  19. g h i
  20. j
  21. # 如果没有 arguments,那么 %s 用NULL代替,%d 用 0 代替
  22. $ printf "%s and %d \n"
  23. and 0
  24. # 如果以 %d 的格式来显示字符串,那么会有警告,提示无效的数字,此时默认置为 0
  25. $ printf "The first program always prints‘%s,%d\n‘" Hello Shell
  26. -bash: printf: Shell: invalid number
  27. The first program always prints ‘Hello,0‘
  28. $

12.Shell if else语句:

Shell 有三种 if ... else 语句:

  • if ... fi 语句;
  • if ... else ... fi 语句;
  • if ... elif ... else ... fi 语句。

 if ... else ... fi 语句

  1. if [ $a == $b ]
  2. then
  3. echo "a is equal to b"
  4. else
  5. echo "a is not equal to b"
  6. fi

 if ... elif ... fi 语句

  1. if [ $a == $b ]
  2. then
  3. echo "a is equal to b"
  4. elif [ $a -gt $b ]
  5. then
  6. echo "a is greater than b"
  7. elif [ $a -lt $b ]
  8. then
  9. echo "a is less than b"
  10. else
  11. echo "None of the condition met"
  12. fi

if ... else 语句也可以写成一行,以命令的方式来运行,像这样:

复制纯文本新窗口

  1. if test $[2*3] -eq $[1+5]; then echo ‘The two numbers are equal!‘; fi;

if ... else 语句也经常与 test 命令结合使用,如下所示:

复制纯文本新窗口

  1. num1=$[2*3]
  2. num2=$[1+5]
  3. if test $[num1] -eq $[num2]
  4. then
  5. echo ‘The two numbers are equal!‘
  6. else
  7. echo ‘The two numbers are not equal!‘
  8. fi

13.Shell case esac语句

case 语句匹配一个值或一个模式,如果匹配成功,执行相匹配的命令。case语句格式如下:

  1. read aNum
  2. case $aNum in
  3. 1)  echo ‘You select 1‘
  4. ;;
  5. 2)  echo ‘You select 2‘
  6. ;;
  7. 3)  echo ‘You select 3‘
  8. ;;
  9. 4)  echo ‘You select 4‘
  10. ;;
  11. *)  echo ‘You do not select a number between 1 to 4‘
  12. ;;
  13. esac

case工作方式如上所示。取值后面必须为关键字 in,每一模式必须以右括号结束。取值可以为变量或常数。匹配发现取值符合某一模式后,其间所有命令开始执行直至 ;;。;; 与其他语言中的 break 类似,意思是跳到整个 case 语句的最后。

取值将检测匹配的每一个模式。一旦模式匹配,则执行完匹配模式相应命令后不再继续其他模式。如果无一匹配模式,使用星号 * 捕获该值,再执行后面的命令。

  1. option="${1}"
  2. case ${option} in
  3. -f) FILE="${2}"
  4. echo "File name is $FILE"
  5. ;;
  6. -d) DIR="${2}"
  7. echo "Dir name is $DIR"
  8. ;;
  9. *)
  10. echo "`basename ${0}`:usage: [-f file] | [-d directory]"
  11. exit 1 # Command to come out of the program with status 1
  12. ;;
  13. esac

14.Shell for循环

  1. for循环一般格式为:for 变量 in 列表
  2. do
  3. command1
  4. ...
  5. commandN
  6. done

例如,顺序输出当前列表中的数字:顺序输出字符串中的字符:

  1. for loop in 1 2 3 4 5 string qwerty
  2. do
  3. echo "The value is: $loop"
  4. done

显示主目录下以 .bash 开头的文件:

  1. #!/bin/bash
  2. for FILE in $HOME/.bash*
  3. do
  4. echo $FILE
  5. done

14.Shell while循环

while循环用于不断执行一系列命令,也用于从输入文件中读取数据;命令通常为测试条件。其格式为:

while command

do

Statement(s) to be executed if command is true

done

命令执行完毕,控制返回循环顶部,从头开始直至测试条件为假。

以下测试条件是:如果COUNTER小于5,那么返回 true。

  1. COUNTER=0
  2. while [ $COUNTER -lt 5 ]
  3. do
  4. COUNTER=‘expr $COUNTER+1‘
  5. echo $COUNTER
  6. done

while循环可用于读取键盘信息。下面的例子中,输入信息被设置为变量FILM,按<Ctrl-D>结束循环。

  1. echo ‘type <CTRL-D> to terminate‘
  2. echo -n ‘enter your most liked film: ‘
  3. while read FILM
  4. do
  5. echo "Yeah! great film the $FILM"
  6. done

15.Shell until循环

与 while 循环在处理方式上刚好相反, until 循环执行一系列命令直至条件为 true 时停止,循环格式为:

until command

do

Statement(s) to be executed until command is true

done

  1. a=0
  2. until [ ! $a -lt 10 ]
  3. do
  4. echo $a
  5. a=`expr $a + 1`
  6. done

command 一般为条件表达式,如果返回值为 false,则继续执行循环体内的语句,否则跳出循环。

16.Shell breakcontinue命令

break命令允许跳出所有循环(终止执行后面的所有循环)。

  1. while :
  2. do
  3. echo -n "Input a number between 1 to 5: "
  4. read aNum
  5. case $aNum in
  6. 1|2|3|4|5) echo "Your number is $aNum!"
  7. ;;
  8. *) echo "You do not select a number between 1 to 5, game is over!"
  9. break
  10. ;;
  11. esac
  12. done

在嵌套循环中,break n命令后面还可以跟一个整数,表示跳出第几层循环:

  1. for var1 in 1 2 3
  2. do
  3. for var2 in 0 5
  4. do
  5. if [ $var1 -eq 2 -a $var2 -eq 0 ]
  6. then
  7. break 2
  8. else
  9. echo "$var1 $var2"
  10. fi
  11. done
  12. done

如上,break 2 表示直接跳出外层循环。

continue命令与break命令类似,只有一点差别,它不会跳出所有循环,仅仅跳出当前循环。

  1. while :
  2. do
  3. echo -n "Input a number between 1 to 5: "
  4. read aNum
  5. case $aNum in
  6. 1|2|3|4|5) echo "Your number is $aNum!"
  7. ;;
  8. *) echo "You do not select a number between 1 to 5!"
  9. continue
  10. echo "Game is over!"
  11. ;;
  12. esac
  13. done

运行代码发现,当输入大于5的数字时,该例中的循环不会结束,语句

  1. echo "Game is over!"

永远不会被执行。

同样,continue 后面也可以跟一个数字,表示跳出第几层循环。

  1. NUMS="1 2 3 4 5 6 7"
  2. for NUM in $NUMS
  3. do
  4. Q=`expr $NUM % 2`
  5. if [ $Q -eq 0 ]
  6. then
  7. echo "Number is an even number!!"
  8. continue
  9. fi
  10. echo "Found odd number"
  11. done

17.Shell函数:Shell函数返回值、删除函数、在终端调用函数

Shell 函数的定义格式如下(关键字 function可以不加)

function function_name () {

list of commands

[ return value ]

}

调用函数只需要给出函数名,不需要加括号。

函数返回值在调用该函数后通过 $? 来获得。

#!/bin/bash

# Define your function here

funcWithReturn(){

echo -n "input a number now!:"  #加 -n 取消输出换行

read numb;

rn=`expr $numb + 2`

return $rn

}

funcWithReturn  #调用函数 无需带()

ret=$?      #使用¥?读取上面的函数返回值

echo "result of funcWithReturn is: $ret"

#函数嵌套:

nestedFunc(){

funcWithReturn    #函数内部调用其他函数 函数嵌套

printf %s\\n $?

}

nestedFunc

像删除变量一样,删除函数也可以使用 unset 命令,不过要加上 .f 选项

  1. $unset .f function_name

如果你希望直接从终端调用函数,可以将函数定义在主目录下的 .profile 文件,这样每次登录后,在命令提示符后面输入函数名字就可以立即调用。

18.Shell函数参数

在Shell中,调用函数时可以向其传递参数。在函数体内部,通过 $n 的形式来获取参数的值,例如,$1表示第一个参数,$2表示第二个参数...funWithParam(){

echo "参数个数 $# !"  # 参数个数

echo "传递给函数的所有参数:$*"  # 传递给函数的所有参数

echo "第一个参数 $1 !"

echo "第二个参数 $2 !"

echo "第十个参数 ${10} !"   #第十个以上的参数就需要带{}访问了

echo "第十一个参数 ${11} !"

}

#调用函数时,后面跟上参数的列表

funWithParam 1 2 3 4 5 6 7 8 9 34 73

注意,$10 不能获取第十个参数,获取第十个参数需要${10}。当n>=10时,需要使用${n}来获取参数。

特殊变量列表

变量

含义

$0

当前脚本的文件名

$n

传递给脚本或函数的参数( 命令行参数 )。n 是一个数字,表示第几个参数。

例如,第一个参数是$1,第二个参数是$2。

$#

传递给脚本或函数的参数个数。

$*

传递给脚本或函数的所有参数。

[email protected]

传递给脚本或函数的所有参数。

被双引号(" ")包含时,与 $* 稍有不同,下面将会讲到。

$?

上个命令的退出状态,或函数的返回值。

$$

当前Shell进程ID。对于 Shell 脚本,就是这些脚本所在的进程ID。

$* [email protected] 的区别:$* [email protected] 都表示传递给函数或脚本的所有参数,不被双引号(" ")包含时,都以"$1" "$2" … "$n" 的形式输出所有参数.

退出状态 : $?可以获取上一个命令的退出状态。大部分命令执行成功会返回 0,失败返回 1($? 也可以表示函数的返回值)

18.Shell输入输出重定向:Shell Here Document/dev/null文件

Unix 命令默认从标准输入设备(stdin)获取输入,将结果输出到标准输出设备(stdout)显示。一般情况下,标准输入设备就是键盘,标准输出设备就是终端,即显示器。

输出重定向:命令的输出不仅可以是显示器,还可以很容易的转移向到文件。语法:  $ command> file

  1. $ who > users     #who命令的输出信息定向到文件users

输出重定向会覆盖文件内容!

如果不希望文件内容被覆盖,可以使用 >> 追加到文件末尾:

$ echo line 2 >> users

$ cat users

输入重定向和输出重定向一样,Unix 命令也可以从文件获取输入,语法为:$command< file

这样,本来需要从键盘获取输入的命令会转移到文件读取内容。

注意:输出重定向是大于号(>),输入重定向是小于号(<)。

$ wc -l users      #计算 users 文件中的行数

也可以将输入重定向到 users 文件: $ wc -l < users

一般情况下,每个 Unix/Linux 命令运行时都会打开三个文件:

  • 标准输入文件(stdin):stdin的文件描述符为0,Unix程序默认从stdin读取数据。
  • 标准输出文件(stdout):stdout 的文件描述符为1,Unix程序默认向stdout输出数据。
  • 标准错误文件(stderr):stderr的文件描述符为2,Unix程序会向stderr流中写入错误信息。

默认情况下,command > file 将 stdout 重定向到 file,command < file 将stdin 重定向到 file。

如果希望 stderr 重定向到 file,可以这样写:

  1. $command 2 > file

如果希望 stderr 追加到 file 文件末尾,可以这样写:

  1. $command 2 >> file

2 表示标准错误文件(stderr)。

如果希望将 stdout 和 stderr 合并后重定向到 file,可以这样写:

  1. $command > file 2>&1     cal > f 2>&1

  1. $command >> file 2>&1

如果希望对 stdin 和 stdout 都重定向,可以这样写:

  1. $command < file1 >file2

command 命令将 stdin 重定向到 file1,将 stdout 重定向到 file2。

全部可用的重定向命令列表

命令

说明

command > file

将输出重定向到 file。

command < file

将输入重定向到 file。

command >> file

将输出以追加的方式重定向到 file。

n > file

将文件描述符为 n 的文件重定向到 file。

n >> file

将文件描述符为 n 的文件以追加的方式重定向到 file。

n >& m

将输出文件 m 和 n 合并。

n <& m

将输入文件 m 和 n 合并。

<< tag

将开始标记 tag 和结束标记 tag 之间的内容作为输入。

19.Here Document 目前没有统一的翻译,这里暂译为嵌入文档Here Document Shell 中的一种特殊的重定向方式,它的基本的形式如下:

  1. command << delimiter
  2. document
  3. delimiter

它的作用是将两个 delimiter 之间的内容(document) 作为输入传递给 command。

注意:

  • 结尾的delimiter 一定要顶格写,前面不能有任何字符,后面也不能有任何字符,包括空格和 tab 缩进。
  • 开始的delimiter前后的空格会被忽略掉。

下面的例子,通过 wc -l 命令计算 document 的行数:

$wc -l << EOF

This is a simple lookup program

for good (and bad) restaurants

in Cape Town.

EOF

3

$

也可以 将 Here Document 用在脚本中,例如:

  1. #!/bin/bash
  2. cat << EOF
  3. This is a simple lookup program
  4. for good (and bad) restaurants
  5. in Cape Town.
  6. EOF

运行结果:

This is a simple lookup program

for good (and bad) restaurants

in Cape Town.

下面的脚本通过 vi 编辑器将 document 保存到 test.txt 文件:

  1. #!/bin/sh
  2. filename=test.txt
  3. vi $filename <<EndOfCommands
  4. i
  5. This file was created automatically from
  6. a shell script
  7. ^[
  8. ZZ
  9. EndOfCommands

运行脚本:

$ sh test.sh

Vim: Warning: Input is not from a terminal

$

打开 test.txt,可以看到下面的内容:

$ cat test.txt

This file was created automatically from

a shell script

$

/dev/null 文件

如果希望执行某个命令,但又不希望在屏幕上显示输出结果,那么可以将输出重定向到 /dev/null:

  1. $ command > /dev/null

/dev/null 是一个特殊的文件,写入到它的内容都会被丢弃;如果尝试从该文件读取内容,那么什么也读不到。但是 /dev/null 文件非常有用,将命令的输出重定向到它,会起到”禁止输出“的效果。

如果希望屏蔽 stdout 和 stderr,可以这样写:

  1. $ command > /dev/null 2>&1

20.Shell文件包含

像其他语言一样,Shell 也可以包含外部脚本,将外部脚本的内容合并到当前脚本。

Shell 中包含脚本可以使用:

  1. . filename

  1. source filename

两种方式的效果相同,简单起见,一般使用点号(.),但是注意点号(.)和文件名中间有一空格。

例如,创建两个脚本,一个是被调用脚本 subscript.sh,内容如下:

  1. url="http://see.xidian.edu.cn/cpp/view/2738.html"

一个是主文件 main.sh,内容如下:

  1. #!/bin/bash
  2. . ./subscript.sh
  3. echo $url

执行脚本:

$chomd +x main.sh

./main.sh

http://see.xidian.edu.cn/cpp/view/2738.html

$

注意:被包含脚本不需要有执行权限。

时间: 2024-12-19 06:54:25

Unix/Linux shell脚本编程学习--Shell Script II的相关文章

Linux Shell脚本编程学习笔记和实战

http://www.1987.name/141.html shell基础 终端打印.算术运算.常用变量 Linux下搜索指定目录下特定字符串并高亮显示匹配关键词 从键盘或文件中获取标准输入 [read命令] 文件的描述符和重定向 数组.关联数组和别名使用 函数的定义.执行.传参和递归函数 条件测试操作与流程控制语句 获取时间日期格式和延时 [date.sleep命令] 内部字段分隔符IFS和脚本的调试DEBUG 显示.读取或拼接文件内容 [cat命令] 文件查找与打印文件列表 [find命令]

shell脚本编程学习笔记(1)

在linux上编程,离不开shell,计划好好看看shell编程,并在这里做些笔记以供有相同兴趣的人分享,主要参考<shell脚本学习指南>. 学习shell脚本编程之前,需要了解脚本编程语言和编译型语言的概念. 一般很多中型.大型的程序是用编译型语言写成的,比如C.C++.Java等.这类程序从源代码编译成目标代码,直接通过计算机执行.编译型语言执行效率比较高,大多运作于底层,处理的是字节.整数.浮点数等机器层级的对象,因此实现一个具体的功能,比如"将一个目录里的所有文件复制到另外

shell脚本编程学习笔记-shell脚本编程基础介绍

一. Shell脚本介绍及第一个规范shell脚本说明 1.1 shell脚本简介 1.1.1 shell是什么? shell是一个命令解释器它在操作系统的最外层负责直接与用户对话把用户的输入解释给操作系统并处理各种各样的操作系统的输入结果输出到屏幕返回给用户,这种对话可以是交互是的(从键盘输入命令可以立即得到shell的回应)或非交互(脚本的方式). 下图中×××的部分就是shell处于操作系统的位置. 1.1.2什么是shell脚本 当linux命令或语句不在命令行下执行(严格的说命令行执行

bash shell脚本编程学习总结

shell脚本编程 编译器-------解释器 静态语言:编译型语言,强类型(变量):事先转换成可执行格式.C/C++/JAVA/C# 动态语言:解释型语言,弱类型.边解释变执行.PHP,SHELL,python,perl 面向过程:shell,c:面向对象:java,python,perl,c++ 变量赋值:VAR_NAME = VALUE: bash变量类型: 环境变量:作用域为当前shell进程及其子进程. export VARNAME=VALUE或者 VARNAME=VALUE expo

源码时代Java干货分享|Shell脚本编程学习入门,只需两个步骤,包你学会!

最近在学习shell编程,对于shell脚本中第一行用于指定脚本解释器的代码到底有没有起到指定解释器的作用感到疑惑,如:#!/bin/bash 在网上查找了不少资料,发现网上竟然也分了两大派,一些人认为#!/bin/bash没有起到作用,因为在shell脚本中#表示是注释的意思,而另一些人则认为是起作用的,但是没有给出令人信服的理由,没办法,我只好自己动手做测试了.1.首先我先创建了一个名为test.sh的shell文件,里面内容如下 这个脚本文件中的第二行代码使用了bash语法,不支持POSI

shell脚本编程学习笔记-case语句

1.case结构条件语句语法 case语句实际上就是规范的多分支if语句 case "字符串变量"in 值1)指令1- ;; 值2)指令2- ;; *)指令3- esac 中文编程语法: case "找女朋友条件"in 有房)嫁给你- ;; 你爸是李刚)嫁给你- ;; 努力吃苦)可以考虑先谈朋友- ;; *)good bye!!! esac 2.简单case脚本 输入1.2.3分别输出对应的值 [[email protected] jiaobenlianxi]# c

shell脚本编程学习笔记(3)sed命令的使用

本文主要参考<sed&awk>. 我们平时使用的编辑器,比如vi,是交互式的编辑器,就是想修改哪个地方,就先定位到哪个地方,通常通过移动光标来完成.而sed是一个非交互式的面向字符流的编辑器,或者叫流编辑器.sed直接处理输入流并将结果送到标准输出.sed通过解释脚本来工作,该脚本指定了将要执行的动作. sed每次从输入文件中读取一个输入行,生成该输入行的备份,并且对改备份执行脚本中指定的指令操作.因此,对输入行所做的改动不会影响到真正的输入行.并且,sed的工作模式,是每次处理输入流

shell脚本编程学习笔记-整数二次元比较操作符

1.1 下表为常用二次元比较操作符 我们也可以通过man test查看 提示 (1) "<"符号是小于的意思,if[[ "$a"<"$b" ]], if[[ "$a"\<"$b" ]].在单括号中需要转义,因为在shell也用<和>做重定向. (2) ">"符号是大于的意思,if[[ "$a"> "$b"

shell脚本编程学习笔记(四)shell操作数据库

一.数据库基本操作 1)登录mysql服务器:mysql -u root -p 密码 2)查看数据库:show databases 3)查看表:show tales from db; 4)查看表结构:desc table; 5)创建表:create table table(); 6)查看表数据:select * from table; 7)插入数据:insert into table(f1,f2) values('v1','v2'); 8)删除数据:delete from table where