Shell编程学习总结

来源:互联网 发布:马云 阿里云 演讲 编辑:程序博客网 时间:2024/06/02 00:48

原文: http://bbs.chinaunix.net/forum.php?mod=viewthread&tid=1945374

0、脚本的执行过程:

./test.sh arg1,操作系统先读取./test.sh文件的首行(#!/bin/sh)得到脚本解释器可执行文件的绝对路径,然后运行该解释器程序,并把该脚本的
文件名和输入的参数传递给该解释器,所以上面脚本的执行相当于:/bin/sh ./test.sh arg1。这种执行过程的方法适用于包括shell/awk/python/perl
/expect等脚本语言。
1、变量
*变量定义:VAR=value,${VAR:=value},变量默认为全局变量,如果加上local则为局部变量,未初始化的变量的初值为空字符串
*变量引用:$VAR,${VAR}
*本地变量:脚本中默认定义的变量都是本地变量,本地变量不能想子脚本进行传递。通过export变成环境变量。
*环境变量:可以被所有的包括新创建的子进程引用到,包括:系统环境变量和export 的变量。
*特殊变量:
  命令行参数:$0脚本名称,$1/2/3...分别表示输入的各个参数,shit后则sn==sn+1,$#参数个数,
  其他特殊变量:$?上一命令的执行结果,$$当前进程的pid,
其他说明:
  1. 变量与变量内容以等号『=』来连结;
  2. 等号两边不能直接接空格符;
  3. 变量名称只能是英文字母与数字,但是数字不能是开头字符;
  4. 若有空格符可以使用双引号 " 或单引号 ' ,来将变量内容结合起来。
  5. 必要时需要以跳脱字符『 \ 』来将特殊符号 ( 如 Enter, $, \, 空格符, ' 等 ) 变成一般符号;
  6. 在一串指令中,还需要藉由其它的指令提供的信息,可以使用 quote 『 ` command` 』;(那个 ` 是键盘上方的数字键 1 左边那个按键,而不是单引号!)
  7. 若该变量为扩增变量内容时,  则需以双引号及 $变量名称 如: "$PATH":/home』继续累加内容;
  8. 若该变量需要在其它子程序执行,  则需要以 export 来使变量变成环境变量, 如export PATH
  9.  通常大写字符为系统预设变量,自行设定变量可以使用小写字符,方便判断。
  10. 取消变量的方法为:『unset 变量名称』。
   
2、函数
function fname() {  //一定要定义在最前面
           程序段   
}
*书写函数定义的时候不需要写参数列表,参数列表都为()
*函数调用方式:fname, fname "$a" "$b" "$c"
*函数局部变量用local修饰,
*函数返回格式:return n;
*函数参数:$1,$2,$3...表示函数的第1/2/3...个参数         
           
3、流程控制
1)条件,分支
if [条件判断] &&/|| [..]: then   if [条件判断] &&/|| [..]: then     if [条件判断] &&/|| [..]: then
fi             else               elif [ 条件判断式二 ]; then  
             fi            else
                      fi
case $变量名称 in
    "第一个变量内容")
   程序段
   ;;
    "第二个变量内容")
   程序段
   ;;
    *)
   不包含第一个变量内容与第二个变量内容的其它程序执行段
   exit 1
   ;;
esac

2)循环

while [ condition ]      until [ condition ]  for (( 初始值; 限制值; 执行步阶 ))    for var in con1 con2 con3 ...
  do            do      do            do
      程序段落     程序段落    程序段落        程序段落
    done          done     done           done
   
   
4、shell内置命令:
内置命令和外部命令不同,外部命令是可以在文件系统的目录下找到可执行文件的,但内置命令则是有bash解释器内部支持的。
常用的内部命令有:echo, eval, exec, export, readonly, read, shift, wait和点(.)。
可以通过:type -tpa [command name] 显示一命令是外部指令还是 bash 内建的指令。
;可以作为两条在一行执行指令的间隔符号

  
5、常用工具:
echo
[]/test
sed
awk
tee
basename  
dirname (注意pwd是打印当前工作路径,而不是文件所在的真实位置,文件真实位置可以用dirname $0来获取,详http://blog.csdn.net/chj90220/article/details/8299573)   

   
4、调试选项

[email=root@linux]root@linux[/email]

~]# sh [-nvx] scripts.sh
参数:
-n  :不要执行 script,仅查询语法的问题;
-v  :再执行 sccript 前,先将 scripts 的内容输出到屏幕上;
-x  :将使用到的 script 内容显示到屏幕上,这是很有用的参数!

set命令用来打开脚本中的选项. 你可以在脚本中任何你想让选项生效的地方插入set -option

-C noclobber 防止重定向时覆盖文件(可能会被>|覆盖)
-D (none) 列出用双引号引用起来的, 以$为前缀的字符串, 但是不执行脚本中的命令
-a allexport export(导出)所有定义过的变量
-b notify 当后台运行的作业终止时, 给出通知(脚本中并不常见)
-c ... (none) 从...中读取命令
-e errexit 当脚本发生第一个错误时, 就退出脚本, 换种说法就是, 当一个命令返回非零值时, 就退出脚本(除了until或while loops, if-tests, list constructs)
-f noglob 禁用文件名扩展(就是禁用globbing)
-i interactive 让脚本以交互模式运行
-n noexec 从脚本中读取命令, 但是不执行它们(做语法检查)
-o Option-Name (none) 调用Option-Name选项
-o posix POSIX 修改Bash或被调用脚本的行为, 使其符合POSIX标准.  
-p privileged 以"suid"身份来运行脚本(小心!)
-r restricted 以受限模式来运行脚本(参考 21).  
-s stdin 从stdin中读取命令
-t (none) 执行完第一个命令之后, 就退出
-u nounset 如果尝试使用了未定义的变量, 就会输出一个错误消息, 然后强制退出
-v verbose 在执行每个命令之前, 把每个命令打印到stdout上
-x xtrace 与-v选项类似, 但是会打印完整命令
- (none) 选项结束标志. 后面的参数为位置参数.  
-- (none) unset(释放)位置参数. 如果指定了参数列表(-- arg1 arg2), 那么位置参数将会依次设置到参数列表中.  

5、判断的标志,应用在test指令或者[]判断中

用来判断一个档是否存在,类型,权限,两个档之间的比较,两个整数之间的比较,字符串之间的判定,多重判断,用的非常广泛
   测试的标志                   代表意义
1. 关于某个档名的『类型』侦测(存在与否),如 test -e filename
      -e    该『档名』是否存在?(常用)
      -f    该『档名』是否为档案(file)?(常用)
      -d    该『文件名』是否为目录(directory)?(常用)
      -b    该『文件名』是否为一个 block device 装置?
      -c    该『文件名』是否为一个 character device 装置?
      -S    该『档名』是否为一个 Socket 档案?
      -p    该『档名』是否为一个 FIFO (pipe) 档案?
      -L    该『档名』是否为一个连结档?
2. 关于档案的权限侦测,如 test -r filename
      -r    侦测该文件名是否具有『可读』的属性?
      -w    侦测该档名是否具有『可写』的属性?
      -x    侦测该档名是否具有『可执行』的属性?
      -u    侦测该文件名是否具有『SUID』的属性?
      -g    侦测该文件名是否具有『SGID』的属性?
      -k    侦测该文件名是否具有『Sticky bit』的属性?
      -s    侦测该档名是否为『非空白档案』?
3. 两个档案之间的比较,如: test file1 -nt file2
      -nt   (newer than)判断 file1 是否比 file2 新
      -ot   (older than)判断 file1 是否比 file2 旧
     判断 file2 与 file2 是否为同一档案,可用在判断 hard link 的
      -ef
     判定上。 主要意义在判定,两个档案是否均指向同一个 inode 哩!
4. 关于两个整数之间的判定,例如 test n1 -eq n2
        -eq        两数值相等 (equal)
        -ne        两数值不等 (not equal)
        -gt        n1 大于 n2 (greater than)
        -lt        n1 小于 n2 (less than)
        -ge        n1 大于等于 n2 (greater than or equal)
        -le        n1 小于等于 n2 (less than or equal)
5. 判定字符串的数据
   test -z string   判定字符串是否为 0 ?若 string 为空字符串,则为 true
            判定字符串是否非为 0 ?若 string 为空字符串,则为 false。
   test -n string
            注: -n 亦可省略
  test str1 = str2 判定 str1 是否等于 str2 ,若相等,则回传 true
  test str1 != str2 判定 str1 是否不等于 str2 ,若相等,则回传 false
6. 多重条件判定,例如: test -r filename -a -x filename
  (and)两状况同时成立!例如 test -r file -a -x file,则 file 同
   -a
  时具有 r 与 x 权限时,才回传 true。
  (or)两状况任何一个成立!例如 test -r file -o -x file,则 file
   -o
  具有 r 或 x 权限时,就可回传 true。
    !    反相状态,如 test ! -x file ,当 file 不具有 x 时,回传 true
   
   
5、其他
1)匹配:
  shell支持简单形式的模式匹配,比如:
  *表示匹配零或者多个字符
  ?仅仅匹配1个字符
  举例:  
      cp test[1-5] /tmp //将 test1/2/3/4/5 若存在的话,就拷贝到 /tmp
      cp test[!1-5]   //和上面相反的意思
      cp test[15]   //只拷贝test1/test5
      
2)引号:
  但须要特别留意, 双引号内的特殊字符可以保有变量特性,但是单引号内的特殊字符则仅为一般字符;
  
3)I/O重定向:
  &digit
  Use file descriptor digit as standard output.      
     >:先清空在填输出结果
     >>:直接在后面追加当前的执行结果
     cmd 2>errorfile:表示将当前指令执行的错误输出进行重导向
    cmd > filename 2>&1:首先将标准输出重定位到filename,然后标准错误输出定义到标准输出上。
          因为标准输出已经在前面定位到了filename上,所以这行语句相当于把标准输出和标准错误输出都重定位到filename上
    cmd > /dev/null 2>&1:相当于直接标准输出和标准错误输出扔到回收站一样,即不显示任何输出。
   
      
4)shell环境设定
  *login shell是在用户第一次用于登录使用的那个shell
      non-login shell不是用于登录用的,可能是用户在后来重新开启任务用到的新的shell
      所有的X-windows下面的终端都是non-login shell
      login 与 non-login shell的最大区别是读取的设定文件不同,non-login shell只会去读区~/.bashrc文件
     
  *系统环境设定文件:
   /etc/sysconfig/i18n:
   /etc/profile:『PATH、USER、MAIL、 HOSTNAME、HISTSIZE、umask』
   /etc/bashrc
   /etc/profile.d/*.sh
   /etc/man.config
  *个人环境设定文件:
   ~/.bash_profile, ~/.bash_login, ~/.profile 只在登录shell时读一此且只会读一个,按照这个顺序读到一个就行
   ~/.bashrc每次执行 shell script 的时候都会被重新使用一遍
   ~/.bash_history每次登录的时候都会读取到内存中
   ~/.bash_logout: logout后希望系统要作的事情
  *各类设定文件的读取顺序:
   /etc/profile->[内部调用的/etc/profile.d 与 /etc/inputrc 等]->[~/.bash_profile, ~/.bash_login, ~/.profile]
   ->~/.bashrc 最后调用
  
  
参考资料:
初学参考:《Learning.the.bash.Shell.3rd.chm》
深入参考:《advance bash script guide.pdf》

快速参考:《man bash》


=====================其他好文章======================

blog.csdn.net/marcky/article/details/7549513