shell-脚本入门【转】

  1. 云栖社区>
  2. 博客>
  3. 正文

shell-脚本入门【转】

sky-heaven 2016-12-07 16:06:00 浏览714
展开阅读全文

转自:http://blog.csdn.net/gexiaobaohelloworld/article/details/7973846

目录(?)[-]

  1. Shell环境设置
    1. 1 登陆欢迎信息
    2. 2 bash环境配置文件
    3. 3 常见的环境变量
      1. 31 环境变量
      2. 32 设置方法
    4. 4 bash中的通配符和特殊符号和组合按键
      1. 41 通配符
      2. 42 特殊字符
      3. 43 组合按键
    5. 4 数据流重定向
    6. 5 命令执行的判断依据
    7. 5 shell脚本调试
  2. 语法基本介绍
    1. 1 开头
    2. 2 注释 
    3. 3 变量 
      1. 34 参数扩展正则表达式
    4. 4 declare
    5. 5 数值计算
      1. 方法1declare -i
      2. 方法2var expression
    6. 6 数组
    7. 7 语句块
    8. 7 特殊变量
    9. 8 输入与输出
    10. 9 Here Document说明文字
    11. 10 退出状态
    12. 11 测试结构与操作符
  3. shell命令与流程控制
    1. 1 Unix 命令 
    2. 3 流程控制 
      1. 31if语句 
      2. 32case
      3. 33 selsect
      4. 34while
      5. 35 until
      6. 36for
      7. 37 beak
      8. 38 continue
    3. 4 source命令和dot命令
    4. 5 export命令
    5. 6 exec命令
    6. 7 shift命令
    7. 8 trap命令
    8. 9 多进程控制
  4. 函数
    1. 1 函数定义语法 
    2. 2 函数返回值的两种办法
    3. 3 实例分析
  5. 我的脚本模板
  6. 实例

http://www.blogjava.net/liubowu/archive/2007/06/25/99317.html

1 Shell环境设置

1.1 登陆欢迎信息

终端机接口 (tty1 ~ tty6) 登陆的时候,会有几行提示的字符串,在在CODE上查看代码片派生到我的代码片
  1. #source ~/.bashrc  
  2. #.  ~/.bashrc  


info bash builtin命令可以列出所有的bash内置命令。

File: bash.info,  Node: Builtin Index,  Next: Reserved Word Index,  Prev: Copying This Manual,  Up: Top

Index of Shell Builtin Commands
*******************************


* Menu:

* .:                                     Bourne Shell Builtins.
                                                              (line  16)
* ::                                     Bourne Shell Builtins.
                                                              (line  11)
* [:                                     Bourne Shell Builtins.
                                                              (line 212)
* alias:                                 Bash Builtins.       (line  11)
* bg:                                    Job Control Builtins.
                                                              (line   7)
* bind:                                  Bash Builtins.       (line  21)
* break:                                 Bourne Shell Builtins.
                                                              (line  29)
* builtin:                               Bash Builtins.       (line  92)
* caller:                                Bash Builtins.       (line 100)
* cd:                                    Bourne Shell Builtins.
                                                              (line  36)
* command:                               Bash Builtins.       (line 117)
* compgen:                               Programmable Completion Builtins.
                                                              (line  10)
* complete:                              Programmable Completion Builtins.
                                                              (line  28)
* continue:                              Bourne Shell Builtins.
                                                              (line  55)
* declare:                               Bash Builtins.       (line 136)
* dirs:                                  Directory Stack Builtins.
                                                              (line   7)
* disown:                                Job Control Builtins.
                                                              (line  83)
* echo:                                  Bash Builtins.       (line 191)
* enable:                                Bash Builtins.       (line 243)
* eval:                                  Bourne Shell Builtins.
                                                              (line  63)
* exec:                                  Bourne Shell Builtins.
                                                              (line  70)
* exit:                                  Bourne Shell Builtins.
                                                              (line  82)
* export:                                Bourne Shell Builtins.
                                                              (line  88)
* fc:                                    Bash History Builtins.
                                                              (line  10)
* fg:                                    Job Control Builtins.
                                                              (line  16)
* getopts:                               Bourne Shell Builtins.
                                                              (line 103)
* hash:                                  Bourne Shell Builtins.
                                                              (line 145)
* help:                                  Bash Builtins.       (line 271)
* history:                               Bash History Builtins.
                                                              (line  39)
* jobs:                                  Job Control Builtins.
 * kill:                                  Job Control Builtins.
                                                              (line  57)
* let:                                   Bash Builtins.       (line 280)
* local:                                 Bash Builtins.       (line 287)
* logout:                                Bash Builtins.       (line 297)
* popd:                                  Directory Stack Builtins.
                                                              (line  37)
* printf:                                Bash Builtins.       (line 301)
* pushd:                                 Directory Stack Builtins.
                                                              (line  58)
* pwd:                                   Bourne Shell Builtins.
                                                              (line 163)
* read:                                  Bash Builtins.       (line 326)
* readonly:                              Bourne Shell Builtins.
                                                              (line 172)
* return:                                Bourne Shell Builtins.
                                                              (line 187)
* set:                                   The Set Builtin.     (line   9)
* shift:                                 Bourne Shell Builtins.
                                                              (line 200)
  * shopt:                                 Bash Builtins.       (line 387)
* source:                                Bash Builtins.       (line 618)
* suspend:                               Job Control Builtins.
                                                              (line  94)
* test:                                  Bourne Shell Builtins.
                                                              (line 212)
* times:                                 Bourne Shell Builtins.
                                                              (line 278)
* trap:                                  Bourne Shell Builtins.
                                                              (line 283)
* type:                                  Bash Builtins.       (line 622)
* typeset:                               Bash Builtins.       (line 653)
* ulimit:                                Bash Builtins.       (line 659)
* umask:                                 Bourne Shell Builtins.
                                                              (line 324)
* unalias:                               Bash Builtins.       (line 737)
* unset:                                 Bourne Shell Builtins.
                                                              (line 341)
* wait:                                  Job Control Builtins.
                                                              (line  73)
                                                           (line  25)

可以通过使用命令info builtin查看所有命令的详细用法
转载:http://blog.chinaunix.net/u2/71769/showart_2226369.html

1.3 常见的环境变量

1.3.1 环境变量

存储在文件/etc/profile中

$PATH:决定了shell将到哪些目录中寻找命令或程序。
$HOME:当前用户主目录。
$MAIL:是指当前用户的邮件存放目录。
$SHELL:是指当前用户用的是哪种Shell。
$HISTSIZE:是指保存历史命令记录的条数。
$LOGNAME:是指当前用户的登录名。
$HOSTNAME:是指主机的名称,许多应用程序如果要用到主机名的话,通常是从这个环境变量中来取得的。
$LANG/LANGUGE:是和语言相关的环境变量,使用多种语言的用户可以修改此环境变量。
$PS1:是基本提示符,对于root用户是#,对于普通用户是$,也可以使用一些更复杂的值。
$PS2:是附属提示符,默认是“>”。
$IFS:输入域分隔符。当shell读取输入时,用来分隔单词的一组字符,它们通常是空格、制表符和换行符。
$0:shell脚本的名字。
$#:传递给脚本的参数个数。
$$:shell脚本的进程号,脚本程序通常会用它生成一个唯一的临时文件,如/tmp/tmfile_$


1.3.2 设置方法

echo:显示指定环境变量。
export:设置新的环境变量。
env:显示所有环境变量。
set:显示所有本地定义的shell变量。
unset:清除环境变量。

将一个路径加入到PATH变量中:

如在PATH 这个变量当中“累加”一个新目录 这个目录

[plain] view plain copy 在CODE上查看代码片派生到我的代码片
  1. #1,控制台中:  
  2. $ PATH="$PATH":/my_new_path"  
  3. #2,修改profile文件:  
  4. $ vi /etc/profile  
  5. 在里面加入:  
  6. export PATH="$PATH:/my_new_path"  
  7. #3,修改.bashrc文件:  
  8. $ vi /root/.bashrc  
  9. 在里面加入:  
  10. export PATH="$PATH:/my_new_path"  
  11. #后两种方法一般需要重新注销系统才能生效,最后可以通过echo命令测试一  

1.4 bash中的通配符和特殊符号和组合按键

注意,这里的通配符虽然和正则表达式相似,但是是基于bash解释器解析的,而正则表达式由正则引擎的软件(如awk,grep,sed等)解析,二者完全不同。

在CODE上查看代码片派生到我的代码片

  1. [root@linux ~]# ls test*     #那个 * 代表后面不论接几个字符都予以接受  
  2. [root@linux ~]# ls test?     #那个 ? 代表后面"一定"要接"一个"字符  
  3. [root@linux ~]# ls test???   #那个 ??? 代表"一定要接三个"字符!  
  4. [root@linux ~]# cp test[1-5] /tmp  # 将 test1, test2, test3, test4, test5 若存在的话,就拷贝到 /tmp  
  5. [root@linux ~]# cp test[!1-5] /tmp # 只要不是 test1, test2, test3, test4, test5 之外的其它 test?拷贝到 /tmp  
  6. [root@linux ~]# cd /lib/modules/`uname -r`/kernel/drivers  # 系统先执行 uname -r 找出输出结果;将结果累加在目录上面,来执行 cd 的功能!  
  7.                      = cd /lib/modules/$(uname -r)/kernel  #另外,这个 quot (`) 的功能,也可以利用 $() 来取代喔!  
  8. [root@linux ~]# cp *[A-Z]* /tmp   #表示文件中包含大写字母  
  9. [root@linux ~]# ls -lda /etc/*[35]* #表示文件中包含数字3或者5.  


1.4.2 特殊字符

# 注释
\ 转义字符
| 管道(pipe)
; 连续命令
~ 用户主文件夹
$ 变量前导符
& 作业控制的后台运行
! 逻辑非
/ 目录分隔符
>,>> 数据流重定向,输出导向,分别是“替换“和”增加“
<,<< 数据流重定向,输入导向
' ‘ 单引号,不具有变量置换功能
” “ 双引号,具有变量置换功能
` ` ` `中内容可以先执行的命令,也可以用$( )来替换
( ) 在中间为子shell的起始与结束
{ } 在中间为命令块的组合

1.4.3 组合按键

Ctrl + C 终止目前的命令
Ctrl + D 输入结束(EOF),例如邮件结束的时候;
Ctrl + M 就是 Enter 啦!
Ctrl + S 暂停屏幕的输出
Ctrl + Q 恢复屏幕的输出
Ctrl + U 在提示字符下,将整列命令删除
Ctrl + Z 暂停目前的命令

1.4 数据流重定向

linux的文件描述符FD,通常为10个:FD0~FD9。可以理解为linux跟踪打开文件,分配的一个数字,linux启动后会默认打开三个文件描述符:
0 标准输入 standard input
1 标准输出standard output
2 错误输出error output 

示例1:
[plain] view plain copy 在CODE上查看代码片派生到我的代码片
  1. ls -al >   newtxt  #本来ls -al 命令预设输出到屏幕,现在被重新导出到newtxt文档。  
  2. ls -al >>  newtxt  #现将ls -al 命令输出结果“增加”到文件newtxt末尾。  

示例2:想要将正确的与错误的数据分别存入不同的档案中:
• 1> :是将正确的数据输出到指定的地方去
• 2> :是将错误的数据输出到指定的地方去
[python] view plain copy 在CODE上查看代码片派生到我的代码片
  1. $ find /home -name testing > list_right 2> list_error  
有 Permission 的那几行错误信息都会跑到 list_error 这个档案中,至于正确的输出数据则会存到 list_right 这个档案中。

示例3:
[plain] view plain copy 在CODE上查看代码片派生到我的代码片
  1. 将错误信息不要(置于垃圾箱中/dev/null)  
  2. $ find /home -name testing > list_right 2> /dev/null   
  3. 将正确输出和错误输出都放置到同一个文件中testing中去  
  4. $ find /home -name testing > list 2> list <==错误写法  
  5. $ find /home -name testing > list 2>&1 <==正确写法  
另外,这里区分一下command>file  2>file 与  command>file 2>&1:
command > file 2>file 的意思是stdout和stderr都直接送到file中, file会被打开两次,这样stdout和stderr会互相覆盖,这样写相当使用了FD1和FD2两个同时去抢占file 的管道.
command >file 2>&1 这条命令就将stdout直接送向file, stderr 继承了FD1管道后,再被送往file,此时,file 只被打开了一次,也只使用了一个管道FD1,它包括了stdout和stderr的内容.

1.5 命令执行的判断依据

分号; cmd;cmd
多条命令顺序执行,执行顺序是从左到右的顺序。
与&& cmd1 && cmd2
若cmd1执行完毕且正确执行($?=0),则开始执行cmd2
若cmd2执行完毕且为错误($? !=0),则cmd2不执行
或|| cmd1 || cmd2
若cmd1执行完毕且正确执行($?=0),则cmd2不执行
若cmd2执行完毕且为错误($? !=0),则开始执行cmd2
注意:这里的&&和||没有优先级关系,而是按照命令次序按序执行,所以对于:
[plain] view plain copy 在CODE上查看代码片派生到我的代码片
  1. ls /tmp/abc || mkdir /tmp/abc && touch /tmp/abc/hehe  
该范例总会创建/tmp/abc/hehe文件。而不是先执行后面的。
[plain] view plain copy 在CODE上查看代码片派生到我的代码片
  1. [ -f file1 ] && exit 0 || exit 1  
该范例如果测试成功,则执行第一条命令,否则执行第二条命令。

1.5 shell脚本调试

Shell提供了一些用于调试脚本的选项,如下所示:
-n   读一遍脚本中的命令但不执行,用于检查脚本中的语法错误
-v   一边执行脚本,一边将执行过的脚本命令打印到标准错误输出
-x   提供跟踪执行信息,将执行的每一条命令和结果依次打印出来
[plain] view plain copy 在CODE上查看代码片派生到我的代码片
  1. $ sh -x ./script.sh  

2 语法基本介绍

2.1 开头

程序必须以下面的行开始(必须放在文件的第一行): 

[plain] view plain copy 在CODE上查看代码片派生到我的代码片
  1. #!/bin/sh   

符号#!用来告诉系统它后面的参数是用来执行该文件的程序,在这个例子中我们使用/bin/sh来执行程序。 

[plain] view plain copy 在CODE上查看代码片派生到我的代码片
  1. chmod +x filename  

当编辑好脚本时,如果要执行该脚本,还必须使其可执行。 这样才能用./filename 来运行。

2.2 注释 

在进行shell编程时,以#开头的句子表示注释,直到这一行的结束。

文档可以这样写:

[python] view plain copy 在CODE上查看代码片派生到我的代码片
  1. ###################################################################################  
  2. ## The script is used for the regression of lineage jar with latest hive-exec..jar  
  3. ## , expression_analyze.jar, parse_common.jar, field_lineage.jar, ast_parser.jar  
  4. ## in trunk.  
  5. ###################################################################################  

区块可以这样写

[python] view plain copy 在CODE上查看代码片派生到我的代码片
  1. ###############################################  
  2. ## PARAMETERS  
  3. ##  

2.3 变量 

2.3.1 变量类型默认为字符串类型

[plain] view plain copy 在CODE上查看代码片派生到我的代码片
  1. #!/bin/sh   
  2. name="Jack"  
  3. s="$name, hello!" #注意等号"="前后都不能有空格。建议字符串用双引号(单引号表示纯字符串,不支持$等)。  
  4. echo $s           #输出Jack, hello!(若s用单引号,则输出$name, hello!)  
  5. unset s           #删除变量s  

2.3.2 单引号,双引号,无引号

[plain] view plain copy 在CODE上查看代码片派生到我的代码片
  1. s="./*"  
  2. echo $s     #这是变量,命令即为echo ./* ,通配符解开为:./1.sh ./a ./b ./c  
  3. echo '$s'   #这里的单引号表示一个字符串,字符串中的$等符号不能转义,输出:$s  
  4. echo "$s"   #这里的双引号表示一个字符串,字符串中的$等符号要转义,其中$s为变量,所以输出./*  

2.3.3 参数扩展——花括号

[plain] view plain copy 在CODE上查看代码片派生到我的代码片
  1. num=2   
  2. echo "this is the $numnd" #this is the   

这并不会打印出"this is the 2nd",而仅仅打印"this is the ",因为shell会去搜索变量numnd的值,但是这个变量时没有值的。可以使用花括号来告诉shell我们要打印的是num变量: 

[plain] view plain copy 在CODE上查看代码片派生到我的代码片
  1. num=2   
  2. echo "this is the ${num}nd" #this is the 2nd  

这将打印: this is the 2nd 

2.3.4 参数扩展——正则表达式

[plain] view plain copy 在CODE上查看代码片派生到我的代码片
  1. ${name:-default} 使用一个默认值(一般是空值)来代替那些空的或者没有赋值的变量name;   
  2. ${name:=default}使用指定值来代替空的或者没有赋值的变量name;  
  3. ${name:?message}如果变量为空或者未赋值,那么就会显示出错误信息并中止脚本的执行同时返回退出码1。  
  4. ${#name} 给出name的长度  
  5. ${name%word} 从name的尾部开始删除与word匹配的最小部分,然后返回剩余部分  
  6. ${name%%word} 从name的尾部开始删除与word匹配的最长部分,然后返回剩余部分  
  7. ${name#word} 从name的头部开始删除与word匹配的最小部分,然后返回剩余部分  
  8. ${name##word} 从name的头部开始删除与word匹配的最长部分,然后返回剩余部分  

举例如下,使用cjpeg命令将一个GIF的文件转换为JPEG的文件:

[plain] view plain copy 在CODE上查看代码片派生到我的代码片
  1. $ cjpeg image.gif > image.jpg  
  2. 也许有时我们会在大量的文件上进行这样的操作.这时我们如何自动重定向?我们可以很容易的这样来做:  
  3. #!/bin/sh  
  4. for image in *.gif  
  5. do  
  6.    cjpeg $image > ${image%%gif}jpg  
  7. done  


2.3.4 注意变量与变量字符串的问题:

[plain] view plain copy 在CODE上查看代码片派生到我的代码片
  1. read a  
  2. if [ $a = "yes" ];then  
  3. echo "OK"  
  4. fi  
  5. if [ "$a" = "yes" ];then  
  6. echo "OK"  
  7. fi  

这里$a是变量a的值,"$a"是对变量a做字符串处理结果。如果read a 时直接回车,那么$a就是空,而不是"",这时程序变成了 if [ = "yes" ]就错了,所以一般用双引号括起来,表示使用字符串值,且转义其中的$变量。

2.3.5 注意打印"*"的问题:

[python] view plain copy 在CODE上查看代码片派生到我的代码片
  1. #!/bin/sh  
  2. sql='select * from gexing;'  
  3. echo  $sql  #其中的*会被替换成所有文件,这就相当于echo select * from table;  
  4. echo "$sql" #这就相当于echo "select * from table"  
2.3.6 变量/字符串连接:
[plain] view plain copy 在CODE上查看代码片派生到我的代码片
  1. names=$var_name1$var_name2   #注意,两个变量之间没有空格  
  2. sentence=${names}"hello"     #直接连接  

2.4 declare

shell中的变量类型默认为字符串类型,但可以通过declare语法来指定变量的其他类型。
[plain] view plain copy 在CODE上查看代码片派生到我的代码片
  1. 语法:  
  2. declare [+/-][afrix]  variable  
  3. 说明:  
  4. +/- "-"可用来指定变量的属性,"+"则是取消变量所设的属性。  
  5. -a 定义变量variable为数组(array)类型  
  6. -i  定义变量variable为整数(integer)类型  
  7. -r  定义变量variable为只读(readonly)类型  
  8. -x  用法与export一样,将variable设置为环境变量  

2.5 数值计算

方法1,declare -i

[plain] view plain copy 在CODE上查看代码片派生到我的代码片
  1. 示例1:让变量 sum 保存 100+300+50 的加和结果  
  2. [root@linux ~]# sum=100+300+50  
  3. [root@linux ~]# echo $sum       #结果为:100+300+50     
  4. [root@linux ~]# declare -i sum=100+300+50  
  5. [root@linux ~]# echo $sum       #结果为:450          
  6.   
  7. 示例2:生成随机数  
  8. [root@linux ~]# declare -i number=$RANDOM*10/32767 ; echo $number  

方法2,var=$ (( expression ))

[plain] view plain copy 在CODE上查看代码片派生到我的代码片
  1. foo=1  
  2. foo=$(($foo+1))  
[plain] view plain copy 在CODE上查看代码片派生到我的代码片
  1. echo $ (( 13 % 3 ))  

2.6 数组

定义:shell支持一维数组,但并不限定数组大小,数组下标从0开始。
修改:对于数组修改操作,可以再对其重新赋值;
删除:如果要删除一个已经赋值后的元素则需要借助一个外部命令:unset,如:unset array[0]可清空下标为0的元素,此时数组大小减一;unset array[@]可以清空整个数组元素所有元素。
[plain] view plain copy 在CODE上查看代码片派生到我的代码片
    1. #!/bin/bash  
    2.   
    3. #赋值  
    4. a[0]=1              #第一种赋值方法  
    5. a[1]=2  
    6. a[2]=3  
    7. b=(6,7,8,9,10)      #第二种赋值方法  
    8.   
    9. #取值  
    10. echo  ${b[0]}       #用${数组名[下标]},下标是从0开始。下标是*或者@,则得到整个数组内容。输出6  
    11. echo  ${b[*]:1:3}   #直接通过${数组名[@或*]:起始位置:长度}切片原先数组,输出7 8 9  
    12. echo  ${b[*]::3}    #输出6 7 8(前三个元素) 
【作者】张昺华
【新浪微博】 张昺华--sky
【twitter】 @sky2030_
【facebook】 张昺华 zhangbinghua
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.

网友评论

登录后评论
0/500
评论