Shell scripts 学习

1 编写脚本

每个脚本的开头都使用"#!",这意味着告诉你的系统这个文件的执行需要指定一个解释器.#!实际上是一个2字节的魔法数字,这是指定一个文件类型的特殊标记, 在#!之后接着是一个路径名.这个路径名指定了一个解释脚本中命令的程序,这个程序可以是shell,程序语言或者是任意一个通用程序.这个指定的程序从头开始解释并且执行脚本中的命令(从#!行下边的一行开始),忽略注释

如:

1 #!/bin/sh 
2 #!/bin/bash 
3 #!/usr/bin/perl 
4 #!/usr/bin/tcl 
5 #!/bin/sed -f 
6 #!/usr/awk -f


2 调用脚本

编写完脚本之后,你可以使用sh scriptname,[5]或者bash scriptname来调用它. 

(不推荐使用sh <scriptname,因为这禁用了脚本从stdin中读数据的功能.) 

更方便的方法是让脚本本身就具有可执行权限,通过chmod命令可以修改. 

比如: 

 chmod 555 scriptname (允许任何人都具有 可读和执行权限) 
 chmod +rx scriptname (允许任何人都具有 可读和执行权限) 
 chmod u+rx scriptname (只给脚本的所有者 可读和执行权限) 

既然脚本已经具有了可执行权限,现在你可以使用./scriptname.来测试它了.如果这个脚本以一个"#!"行开头,那么脚本将会调用合适的命令解释器来运行. 

最后一步,在脚本被测试和debug之后,你可能想把它移动到/usr/local/bin(当然是以root身份) ,来让你的脚本对所有用户都有用.这样用户就可以直接敲脚本名字来运行了

为什么不直接使用scriptname来调用脚本?

如果你当前的目录下($PWD)正好有你想要执行的脚本,为什么它运行不了呢?失败的原因是,出于安全考虑,当前目录并没有被加在用户的$PATH变量中.

因此,在当前目录下调用脚本必须使用./scriptname这种形式. 二元比较操作符,比较变量或者比较数字.注意数字与字符串的区别. 


3 比较操作 

整数比较

-eq  等于,如:if [ "$a" -eq "$b" ] 
-ne  不等于,如:if [ "$a" -ne "$b" ] 
-gt  大于,如:if [ "$a" -gt "$b" ] 
-ge  大于等于,如:if [ "$a" -ge "$b" ] 
-lt  小于,如:if [ "$a" -lt "$b" ] 
-le  小于等于,如:if [ "$a" -le "$b" ] 
<  小于(需要双括号),如:(("$a" < "$b")) 
<=  小于等于(需要双括号),如:(("$a" <= "$b")) 
>  大于(需要双括号),如:(("$a" > "$b")) 
>=  大于等于(需要双括号),如:(("$a" >= "$b")) 

字符串比较

=     等于,如:if [ "$a" = "$b" ] 
==  等于,如:if [ "$a" == "$b" ],与=等价

      注意:==的功能在[[]]和[]中的行为是不同的,如下: 
     1 [[ $a == z* ]]     # 如果$a以"z"开头(模式匹配)那么将为true 
     2 [[ $a == "z*" ]]   # 如果$a等于z*(字符匹配),那么结果为true 
     3 
     4 [ $a == z* ]       # File globbing 和word splitting将会发生
     5 [ "$a" == "z*" ]   # 如果$a等于z*(字符匹配),那么结果为true 
     一点解释,关于File globbing是一种关于文件的速记法,比如"*.c"就是,再如~也是. 但是file globbing并不是严格的正则表达式,虽然绝大多数情况下结构比较像. 

<    小于,在ASCII字母顺序下.如: 
      if [[ "$a" < "$b" ]] 
      if [ "$a" \< "$b" ] 
       注意:在[]结构中"<"需要被转义. 

>  大于,在ASCII字母顺序下.如: 
     if [[ "$a" > "$b" ]] 
      if [ "$a" \> "$b" ] 
      注意:在[]结构中">"需要被转义. 

-z    字符串为"null".就是长度为0. 
-n    字符串不为"null" 

注意: 
使用-n在[]结构中测试必须要用""把变量引起来.使用一个未被""的字符串来使用! -z 或者就是未用""引用的字符串本身,放到[]结构中

虽然一般情况下可以工作,但这是不安全的.习惯于使用""来测试字符串是一种好习惯

混合比较

-a  逻辑与
      exp1 -a exp2 如果exp1和exp2都为true的话,这个表达式将返回true 
-o  逻辑或
       exp1 -o exp2 如果exp1和exp2中有一个为true的话,那么这个表达式就返回true 

        这与Bash的比较操作符&&和||很相像.在[[]]中使用它. 
  1 [[ condition1 && condition2 ]] 
-o和-a一般都是和test命令或者是[]一起工作. 
  1 if [ "$exp1" -a "$exp2" ] 


4 变量替换、赋值

$  变量替换操作符
    只有在变量被声明,赋值,unset或exported或者是在变量代表一个signal的时候, 变量才会是以本来的面目出现在脚本里.

变量在被赋值的时候,可能需要使用"=", read状态或者是在循环的头部. 在""中还是会发生变量替换,这被叫做部分引用,或叫弱引用.

而在''中就不会发生变量替换,这叫做全引用,也叫强引用.

       注意:$var与${var}的区别,不加{},在某些上下文将引起错误,为了安全,使用${var}


=  赋值操作符(前后都不能有空白) 

   不要与-eq混淆,那个是test,并不是赋值. 注意,=也可被用来做test操作,这依赖于上下文


Bash变量是不分类型的

不像其他程序语言一样,Bash并不对变量区分"类型".本质上,Bash变量都是字符串. 但是依赖于上下文,Bash也允许比较操作和算术操作.

决定这些的关键因素就是,变量中的值是否只有数字


特殊的变量类型

local variables

        这种变量只有在代码块或者是函数中才可见

environmental variables 
     这种变量将改变用户接口和shell的行为. 
     在一般的上下文中,每个进程都有自己的环境,就是一组保持进程可能引用的信息的变量.这种情况下,shell于一个一般进程是相同的. 

     每次当shell启动时,它都将创建自己的环境变量.更新或者添加新的环境变量,将导致shell更新它的环境,同时也会影响所有继承自这个环境的所有子进程(由这个命令
导致的). 

       注意:分配给环境变量的空间是受限的.创建太多的环境变量将引起空间溢出,这会引起问题. 

       如果一个脚本设置了环境变量,需要export它,来通知本脚本的环境脚本只能对它产生的子进程export变量.

一个从命令行被调用的脚本export的变量,将不能影响调用这个脚本的那个命令行shell的环境. 

positional parameters 

       就是从命令行中传进来的参数,$0, $1, $2, $3... 
       $0就是脚本文件的名字,$1是第一个参数,$2为第2个...,以后就需要打括号了,如${10},${11},${12}... 

       两个值得注意的变量$*和$@,表示所有的位置参数.


引用变量

在一个双引号中直接使用变量名,一般都是没有问题的.它阻止了所有在引号中的特殊字符的重新解释--包括变量名--但是$,`和\除外.保留$,作为特殊字符的意义,是为了能够在双
引号中也能够正常地引用变量("$var").这样在""中可以使用变量所表达的值 

使用""来防止单词分割.[4]如果在参数列表中使用双引号,将使得双引号中的参数作为一个参数.即使双引号中的字符串包含多个单词(也就是包含空白部分),也不会变为多个参数

单引号操作总体上和""很像,但不允许引用变量.因为$的特殊含义被关闭了.在''中除了',其他字符都没有特殊的含义了.所以单引号比双引号严格


转义

转义是一种引用单个字符的方法.一个具有特殊含义的字符前边放上一个转义符(\)就告诉shell 这个字符失去了特殊的含义. 

值得注意的是,在某些特定的命令和工具中,比如echo和sed,转义符往往会起到相反的效果, 它反倒有可能引发出这个字符特殊的含义. 

对于特定的转义符的特殊的含义

在echo和sed中所使用的
\n  意味着新的一行
\r  回车
\t  tab键
\v  vertical tab(垂直tab),查前边的Ctl-K 
\b  backspace,查前边的Ctl-H 
\a  "alert"(如beep或flash) 
\0xx 转换成8进制ASCII解码,等价于oxx 


5 退出和退出状态

exit命令被用来结束脚本,就像C语言一样.他也会返回一个值来传给父进程,父进程会判断是否可用. 

每个命令都会返回一个exit状态(有时候也叫return状态).成功返回0,如果返回一个非0值,通常情况下都会被认为是一个错误码.一个编写良好的UNIX命令,程序,和工具都会返回一个0作为退出码来表示成功,虽然偶尔也会有例外. 

同样的,脚本中的函数和脚本本身都会返回退出状态.在脚本或者是脚本函数中执行的最后的命令会决定退出状态.

在脚本中,exit nnn命令将会把nnn退出码传递给shell(nnn必须是10进制数0-255). 

当一个脚本以不带参数exit来结束时,脚本的退出状态就由脚本中最后执行命令来决定. 

$?读取最后执行命令的退出码.函数返回后,$?给出函数最后执行的那条命令的退出码.这种给函数返回值的方法是Bash的方法.对于脚本来说也一样.总之,一般情况下,0为成功,非0失败W.



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值