linux shell 脚本学习

来源:互联网 发布:python数据挖掘薪资 编辑:程序博客网 时间:2024/05/16 10:30
shell 是一种脚本语言linux /unix 上常见的Shell脚本解释器有bash、sh、csh、ksh、ash。
最常用的是bash、sh。下面我们就以sh为例子来说明。


1 指定脚本解释器
  我们以 #!开头指定解释器,例如
  #!/bin/tcsh
  通常我们将这一句放在脚本的开始处。(当然,如果不放在开头不会出错).
  
2 注释
  以#开始为注释,shell脚本只支持单行脚本。#号可以在一行的开头,也可以在这一行的中间。#号之后都是注释
  例如 
  # this is notes
  echo "this " #this is notes
  
3 变量
  定义变量的语句如下:
  变量名=变量值
  变量名必须以字母开头,可以包括字母、数字、下划线。
  变量值可以是数值或者字符串。如果字符串必须用双引号括起来。
  在等号两边不能空格。
  定义变量举例:
  a=5
  str="test"
  都是合法的。
  而
  a = 5 
  就是非法的。
  变量赋值后还可以重新赋值,例如
  aa="test"
  aa="test again"
  echo ${aa}
  那么这段代码执行结果就是在命令行显示了test again。
  
  我们还可以用readonly定义只读变量
  例如:
  a=5
  readonly a
  a="56"
  echo $a
  那么echo显示的结果还是5.
  
  一些预定义的特殊变量
  $0 当前脚本的文件名
  $n 传递给脚本或函数的参数。n 是一个数字,表示第几个参数。例如,第一个参数是$1,第二个参数是$2。
  $# 传递给脚本或函数的参数个数。
  $* 传递给脚本或函数的所有参数
  $@ 传递给脚本或函数的所有参数。
  $?    获取上一个命令的返回值,一般情况下执行成功返回0 ,失败返回非0值
  $$    当前Shell进程ID。对于 Shell 脚本,就是这些脚本所在的进程ID。
  注意:$*和$@的区别在于
  for var in "$*"
  do
  echo "$var"
  done
  和
  for var in "$@"
  do
    echo "$var"
  done
  $@会返回每一个参数
  例如我们输入3个参数 
  ./test.sh aa ab ac
  那么 
  for var in "$*"
  do
  echo "$var"
  done
  执行完显示的是
  aa ab ac
  而
  for var in "$@"
  do
    echo "$var"
  done
  执行完显示的是
  aa
  ab
  ac
  
  变量的替换
  ${var:-data}   如果变量为空,或者已经删除,则返回data的值,但不改变var的值。
  ${var:=data}   如果变量为空,或者已经删除,则返回data的值,并且将var设置为data。
  ${var:?message}如果变量为空,或者已经删除,则将message送到标准错误输出。如果此语句出现在脚本中,脚本将停止
  ${var:+data}   如果变量已经定义,则返回data的值,但不改变var的值。
  
  
4 命令替换
  `command` 先执行command命令,将输出结果暂时保存
  注意:`是反引号,在esc键的下面。
  例如下面的脚本
#!/bin/bash
myfun()
{
echo "123"


}


myfun
echo "test1"
DATA=`myfun`
echo "test2"
echo "var = ${DATA}"
执行结果就是
123
test1
test2
var=123


5 常用运算符
5.1 数学运算
    加法 expr a + b  
    减法 expr a - b  
    乘法 expr a \* b  
    除法 expr b / a 结果为 2。
    取余 expr b % a 结果为 0。
    相等。用于比较两个数字,相同则返回 true。 [ a == b ]  
    不相等。用于比较两个数字,不相同则返回 true。 [ a != b ]  
    
注意 a b必须为数字或者变量 a b 和运算符之间必须有空格,例如 expr 5+3是错误的。 expr 5 + 3  或者expr $a + $b 是正确的
加减乘除取余可以个变量赋值,例如:
data=`expr 5 + 3`


相等和不想等只能用于条件判断,不能赋值


5.2 关系运算符


    -eq 检测两个数是否相等,相等返回 true。   例如[ $a -eq $b ]  
    -ne 检测两个数是否相等,不相等返回 true。例如[ $a -ne $b ]  
    -gt 检测左边的数是否大于右边的,如果是,则返回 true。例如[ $a -gt $b ]  
    -lt 检测左边的数是否小于右边的,如果是,则返回 true。例如[ $a -lt $b ]  
    -ge 检测左边的数是否大等于右边的,如果是,则返回 true。例如[ $a -ge $b ]  
    -le 检测左边的数是否小于等于右边的,如果是,则返回 true。例如[ $a -le $b ]  
    
5.3 布尔运算符
 
   ! 非运算,表达式为 true 则返回 false,否则返回 true。例如[ ! false ]  
   -o 或运算,有一个表达式为 true 则返回 true。例如[ $a -lt 20 -o $b -gt 100 ]  
   -a 与运算,两个表达式都为 true 才返回 true。例如[ $a -lt 20 -a $b -gt 100 ]  
   
5.4 字符串运算符列表
 
= 检测两个字符串是否相等,相等返回 true。   例如[ $a = $b ]  
!= 检测两个字符串是否相等,不相等返回 true。例如[ $a != $b ]  
-z 检测字符串长度是否为0,为0返回 true。例如[ -z $a ]  
-n 检测字符串长度是否为0,不为0返回 true。例如[ -z $a ]  
str 检测字符串是否为空,不为空返回 true。例如[ $a ]  

5.5 文件测试运算符


-b file 检测文件是否是块设备文件,如果是,则返回 true。  
-c file 检测文件是否是字符设备文件,如果是,则返回 true。  
-d file 检测文件是否是目录,如果是,则返回 true。  
-f file 检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回 true。  
-g file 检测文件是否设置了 SGID 位,如果是,则返回 true。  
-k file 检测文件是否设置了粘着位(Sticky Bit),如果是,则返回 true。  
-p file 检测文件是否是具名管道,如果是,则返回 true。  
-u file 检测文件是否设置了 SUID 位,如果是,则返回 true。  
-r file 检测文件是否可读,如果是,则返回 true。  
-w file 检测文件是否可写,如果是,则返回 true。  
-x file 检测文件是否可执行,如果是,则返回 true。  
-s file 检测文件是否为空(文件大小是否大于0),不为空返回 true。  
-e file 检测文件(包括目录)是否存在,如果是,则返回 true。  

6 字符串
字符串可以直接赋值,也可以用单引号或者双引号。例如
str=test
str='test'
str="test"
都是正确的。
如果字符串中出现单引号或者双引号,要用\来转义。

单引号和双引号的区别在于,双引号中可以出现变量,单引号中不行例如
str="num is ${var}"

单引号字串中不能出现单引号(对单引号使用转义符后也不行)。

字符串的拼接
例如
var="test"
var2="test2"
echo "var ="$var" !"
echo $var$var2
都是正确的

字符串的操作
${#string} 获取字符串string的长度
${string:position}在字符串string中, 从位置position开始提取子串(下标从0开始)
${string:position:length}在字符串string中, 从位置position开始提取长度为length的子串
${string#substring}从变量$string的开头, 删除最短匹配$substring的子串
例如:
string="linux test start"
echo ${string##li}  
运行结果就是nux test start

${string##substring}从变量$string的开头, 删除最长匹配$substring的子串
${string%substring}从变量$string的结尾, 删除最短匹配$substring的子串
${string%%substring}从变量$string的结尾, 删除最长匹配$substring的子串
   
${string/substring/replacement}使用$replacement, 来代替第一个匹配的$substring
例如
string="linux test start test"
echo ${string/test/love} 
运行结果就是linux love start test

${string//substring/replacement}使用$replacement, 代替所有匹配的$substring
例如
string="linux test start test"
echo ${string//test/love} 
运行结果就是linux love start love

${string/#substring/replacement}如果$string的前缀匹配$substring, 那么就用$replacement来代替匹配到的$substring
注意这个是从头匹配的。
${string/%substring/replacement}如果$string的后缀匹配$substring, 那么就用$replacement来代替匹配到的$substring
注意这个是从尾匹配的

expr index "$string" char 查找字符char的位置,下标从1开始
例如
string="linux test start test"
echo `expr index "$string" x` 
运行结果就是5


7 数组
  定义数组
  可以直接定义例如 arraybuf=("123" "234" "345" "456")
  或者单独定义数组的各个元素
  array[0]="123"
  array[1]="234"
  数组元素的使用,可以直接访问例如
  echo "${arraybuf[0]}"
  echo "${array[0]}"
  
  使用@ 或 * 可以获取数组中的所有元素
  例如
  echo "${arraybuf[@]}"
  echo "${array[*]}"
  执行的结果就是
  123 234 345 456
  123 234
  
  获取数组长度
  ${#array_name[@]} 或者${#array_name[*]}
  例如
  arraybuf=("123" "234" "345" "456")
  array[0]="123"
  array[1]="234"
  length=${#arraybuf[@]}
  length2=${#array[*]}
  echo "len=$length $length2"
  执行的结果就是
  len=4 2
  
8 if语句
  if [ expression ]
  then
     Statement(s) to be executed if expression is true
  fi
  
  if [ expression ]
  then
     Statement(s) to be executed if expression is true
  else
     Statement(s) to be executed if expression is not true
  fi
  
  
  if [ expression 1 ]
  then
     Statement(s) to be executed if expression 1 is true
  elif [ expression 2 ]
  then
      Statement(s) to be executed if expression 2 is true
  elif [ expression 3 ]
  then
       Statement(s) to be executed if expression 3 is true
  else
       Statement(s) to be executed if no expression is true
  fi
  
  下面是例子:
a=5
b=6
if [ $a -eq $b ]
then
echo "a==b"
elif [ $a -gt $b ]
then
echo "a>b"
else
echo "a<b"
fi
运行下面的代码,那么结果是打印“a<b”
这里需要注意的是,在if后面的条件是方括号,不是圆括号。另外方括号的前后要有空格。
例如if[$a -eq $b] 或者if[ $a -eq $b ]或者if ( $a -eq $b )都是错误的。


9 case语句
shell脚本里面的case语句类似C语言中的switch,是一种多分支选择
下面是语法描述
case value in
data)
    command1
    ;;
data)
    command2
    command3
    ;;
*)
    command4
    ;;
esac


下面是例子
a=5
case a in
1 )
    echo "a is 1"
    ;;
2 )
    echo "a is 2"
    ;;
* )
    echo "a is not 1 or 2"
    echo "a is $a"
    ;;
esac
运行上面的例子
将会打印
a is not 1 or 2
a is 5
注意:case的每一个分支可以有一行或多行语句,每个分支以两个分号结束,两个分号相当于C语言的break.
data后面的括号,可以有空格,也可以没有,例如1)或者1 )都是正确的
*)相当于C语言的default语句


10 for 语句
for 语句的格式如下
for value in list
do
    command1
    command2
    ...
done


下面是例子:
for a in 1 2 3
do 
echo "a=$a"
done
执行结果就是
a=1
a=2
a=3


for还可以用于字符串
for a in this is test
do 
echo "a=$a"
done
执行结果就是
a=this
a=is
a=test


下面的例子是列出HOME目录下的所有文件
for a in $HOME/*
do 
echo "file=$a"
done


11 while语句


格式为:
while [ condition ]
do
   command
done


while语句和C语言的while是一样的,condition为真时(条件成立),执行。为false时跳出循环
例如
a=0
while [ $a -lt 5 ]
do
    a=`expr $a + 1`
    echo $a
done
执行的结果就是
1
2
3
4
5






12 until语句


格式为:
until [ condition ]
do
   command
done


until与while正好相反,当condition为false是执行,为true时跳出循环


例如
a=0
until [  $a -gt 5 ]
do
    a=`expr $a + 1`
    echo $a
done
执行结果为
1
2
3
4
5
6


13 break语句
   break和C语言的一样,跳出循环。
   例如
for a in 1 2 3 4 5 6
do
if [ $a -eq 4 ]
then
break
else
echo "a=$a"
fi
done
执行结果就是
a=1
a=2
a=3


14 continue 语句
   continue 也和c语言一样的。
   例如
for a in 1 2 3 4 5 6
do
if [ $a -eq 4 ]
then
continue
else
echo "a=$a"
fi
done
执行结果就是
a=1
a=2
a=3
a=5
a=6




15 函数的定义
函数的定义格式如下
function_name () {
    commands
    return value 
}
或者
function function_name () {
    list of commands
    return value 
}
函数可以返回值,也可以不返回


而函数的调用直接写函数的名字就可以了


例如
fun() {
   echo "fun test"
}
function fun2() {
  return 5

fun
fun2
a=$?
echo "a=$a"
执行结果就是
fun test
a=5


函数也可以带参数,参数一次时$1 S2 ...
例如
fun() {
   echo "fun para1 $1"
   echo "fun para1 $2"
}
 
fun 5 10
执行的结果就是
fun para1 5
fun para1 10




16 输出重定向


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


$command 2 > file    :stderr 重定向到 file
$command 2 >> file   :stderr 追加到 file 文件末尾
$command > file 2>&1 :将 stdout 和 stderr 合并后重定向到 file
$command >> file 2>&1:将 stdout 和 stderr 合并后追加到 file 文件末尾


17 shell 中包含脚本
shell中包含脚本可以用
. filename
或者
source filename
注意.后面有空格。


18 [] &&  ||说明
   []相当与test ,将返回是否为真
   && 当&&前面的条件成立,才会执行,&& 后面的语句
   || 当||前面的条件不成立,才会执行||后面的语句
   
   例如:
a=5
[ $a -eq 5 ] && echo "a=5"
[ $a -gt 5 ] && echo "a>5"
执行结果为
a=5


a=5
[ $a -eq 5 ] || echo "a=5"
[ $a -gt 5 ] || echo "a>5"
执行结果就是
a>5
0 0
原创粉丝点击