Linux - shell script

Shell Script

  • Shell Script
    • 一、概念
    • 二、shell script编写需要注意的事项
    • 三、test命令
      • (一)、多重条件判断
      • (二)、判断字符串
      • (三)、判断数字
      • (四)、判断文件
      • 拓展:判断符号[]的使用
    • 四、shell script 的默认变量($0 $1)
      • shift 造成参数变量号码偏移
    • 五、条件判断式
      • (一)、if…then
        • 1. 简单条件判断式
        • 2.多重、复杂条件判断式
      • (二)、case…esac
    • 六、function 功能
    • 七、循环(loop)
      • (一)、while do done, until do done 不定循环
      • (二)、for…do..done(for循环)
    • 八、shell script的追踪和调试
    • 注:
      • 1. 介绍shell中字符串大小写转换的方式

一、概念

​ shell script 就是利用shell的功能所写的程序,这个程序是使用纯文本文件,将一些shell的语法和命令(包括外部命令)写在里面,搭配正则表达式、管道命令和数据流重定向等功能,以达到我们的目的。

二、shell script编写需要注意的事项

假设存在/home/dmtsat/shell.sh

  • 命令执行顺序,从上至下,从左至右

  • 命令执行会忽略空白

  • 空白行也会被忽略

  • tab视为空白

  • 读取到enter符号,就尝试开始执行该行(或该串)命令

  • 如果需要换行的话,可以使用 \[Enter]来扩展到下一行

  • #可以作为批注, 也就是注释

  • 直接命令执行:shell.sh文件必须要具备可读和可执行(rx)权限

    • 绝对路径

    /home/dmtsai/shell.sh

    • 相对路径

    工作目录在 /home/dmtsai 命令:./shell.sh

  • 以bash执行的话,通过 bash shell.sh 或者 sh shell.sh执行

三、test命令

test命令用于检查文件类型和比较值,并且根据表达式的值来确定状态并退出。所以如果只执行test命令,是不会有任何输出的,可以使用echo $?来查看上次执的状态码(0表示成功,其他值则表示不成功)。用在Shell Script中可以作为判读语句和if..then一起使用,如果在终端输出打印,则经常和管道命令&&||一起使用,如:

$ test 1 -ge 2 && echo "yes" || echo "no"
no12

(一)、多重条件判断

shell中提供了逻辑运算符-a, -o, !,表示与,或,非:

test Expression     # 表达式是否为true
test ! Expresssion  # 表达式是否为false
test Expression1 -a Expression2  # 表达式1和2都是否为true
test Expression1 -o Expression2  #是否表达式1或2为true1234

如:

# 如果1>0 且 2>3,输出true,否则false
$ test 1 -gt 0 -a 2 -gt 3 &&echo "true" || echo "false"
false
# 如果1>0 或 2>3,输出true,否则false
$ test 1 -gt 0 -o 2 -gt 3 &&echo "true" || echo "false"
true
# 如果1>1或2>3,输出true,否则false
$ test 1 -gt 1 -o 2 -gt 3 &&echo "true" || echo "false"
false123456789

(二)、判断字符串

test命令也可以判断字符串长度是否为0,还可以比较两个字符串:

test -n String    # 字符串长度不为0则为true
test String       #等效-n参数
test -z String    # 字符串长度为0,则为true
test String1 = String2   #字符串1和2相等,则为true注意空格
test String != String2    # 字符串1和字符串2不等,则为true12345

如:

$ test "" && echo "true" || echo "false"
false
$ test "12123" && echo "true" || echo "false"
true
$ test -n "" && echo "true" || echo "false"
false
$ test -z "" && echo "true" || echo "false"
true
$ test "123" = "132" && echo "true" || echo "false"
false
$ test "123" = "123" && echo "true" || echo "false"
true
$ test "123" != "132" && echo "true" || echo "false"
true
$ test "123" != "123" && echo "true" || echo "false"
false12345678910111213141516

(三)、判断数字

test命令可用来比较两个数的大小:

test Integer1 -eq Integer2    #数字1等于数字2,则为true
test Integer1 -ge Integer2    #数字1大于等于数字2,则为true
test Integer1 -gt Integer2    #数字1大于数字2,则为true
test Integer1 -le Integer2    #数字1小于等于数字2,则为true
test Integer1 -lt Integer2    #数字1小于数字2,则为true
test Integer1 -ne Integer2    #数字1不等于数字2,则为true123456

如:

$ test 1 -le 0 && echo "true" || echo "false"
false
$ test 1 -ge 0  && echo "true" || echo "false"
true
$ test 1 -gt 0  && echo "true" || echo "false"
true
$ test 1 -lt 0  && echo "true" || echo "false"
false
$ test 1 -ne 0  && echo "true" || echo "false"
true12345678910

(四)、判断文件

test -b FILE    #文件是否存在并且是块设备

test -c FILE    #文件是否存在并且是字符文件

test -d FILE    #文件是否存在并且是目录(常用)

test -e FILE    #文件是否存在(常用)

test -f FILE    #文件是否存在并且是普通文件(常用)

test -h FILE    #文件是否存在并且是连接文件

test -L FILE    #等效于-h

test -p FILE    #文件是否存在且为一个管道文件(FIFO)

test -r FILE    #文件是否存在并且具有可读权限

test -s FILE    #文件是否存在并且文件大小不为0

test -S FILE    #文件是否存在并且是一个Socket

test -t FD      #文件描述符FD是否在终端打开

test -w FILE    #文件是否存在并且具有可写权限

test -x FILE    #文件是否存在并且具有可执行权限

如:

# 当前目录下存在一个android文件夹
$ ls -l
total 4
drwxrwxr-x 2 root root 4096 626 16:50 testFile
$ test -e testFile && echo "true" || echo "false"
true
$ test -b testFile && echo "true" || echo "false"
false
$ test -c testFile && echo "true" || echo "false"
false
$ test -d testFile && echo "true" || echo "false"
true
$ test -e testFile && echo "true" || echo "false"
true
$ test -f testFile && echo "true" || echo "false"
false
$ test -h testFile && echo "true" || echo "false"
false
$ test -r testFile && echo "true" || echo "false"
true
$ test -s testFile && echo "true" || echo "false"
true
$ test -S testFile && echo "true" || echo "false"
false
$ test -w testFile && echo "true" || echo "false"
true
$ test -x testFile && echo "true" || echo "false"
true

拓展:判断符号[]的使用

在shell script中,除了经常使用test命令来判断表达式外,还可以使用判断符号[],不过需要注意一下几点:

  • 1.判断符号中的每个组件必须使用空格来分隔;
  • 2.判断符号中的变量使用双引号扩起来;
  • 3.判读符号中的常量使用双引号或者单引号扩起来。
    如:
$ name=shell
$ [ "$name" == "shell" ] && echo "true" || echo false
true123

判断符号中也支持逻辑运算符-a,-o,!,以及test命令中的一些判断参数,如:

$ [ "$name" == "shells" -a 1 -gt 0 ] && echo true || echo false 
false

四、shell script 的默认变量($0 $1)

执行命令: /path/to/scriptname   opt1   opt2   opt3

默认变量 : $0 $1 \$2 \$3

默认变量 含义
$0 当前脚本的文件名
n|n n | 传 递 给 脚 本 的 参 数 。 n 是 一 个 数 字 , 表 示 第 几 个 参 数 。 例 如 , 第 一 个 参 数 是 1,第二个参数是$2
$# 传递给脚本或函数的参数个数。
|" ∗ | 传 递 给 脚 本 或 函 数 的 所 有 参 数 。 代 表 : " 1c 2c 2 c 3” 其中c为分隔符,默认为空格键
$@ 传递给脚本或函数的所有参数。被双引号(” “)包含时,与 $* 稍有不同。代表:”$1” 、”$2”、 “$3”
$? 上个命令的退出状态,或函数的返回值。
$$ 当前Shell进程ID。对于 Shell 脚本,就是这些脚本所在的进程ID。

shift 造成参数变量号码偏移

[root@iZ2zee88b1mcsq6mmf7w95Z ~]# cd scripts/; cat sh03.sh
#!/bin/bash
# Program:
#   This program is hello world!
#
echo "Total  ->  $#"
echo "whole -> '$@'"
shift
echo "num -> $#"
echo "whole -> '$@'"
shift 3
echo "num -> $#"
echo "whole -> '$@'"

exit 0
[root@iZ2zee88b1mcsq6mmf7w95Z scripts]# ./sh03.sh one two three four five six seven
Total  ->  7
whole -> 'one two three four five six seven'
num -> 6
whole -> 'two three four five six seven'
num -> 3
whole -> 'five six seven'
[root@iZ2zee88b1mcsq6mmf7w95Z scripts]#

shift 后面接数字,就是去掉最前面的几个参数。

五、条件判断式

(一)、if…then

1. 简单条件判断式

if [条件判断式]; then
    当条件成立后,可以进行的命令工作内容;
fi 
#fi表示结束if

举例子吧 输入 yes or no

[root@iZ2zee88b1mcsq6mmf7w95Z scripts]# nl sh04.sh 
     1  #!/bin/bash
     2  # Program:
     3  #   This program is hello world!
     4  #

     5  read -p "please input(y/n):" result

     6  if [ "$result" == "Y" ] || [ "$result" == "y" ] ; then
     7      echo "yes"
     8      exit 0
     9  fi
    10  if [ "$result" == "N" ] || [ "$result" == "n" ] ; then
    11          echo "no"
    12          exit 0
    13  fi
    14  exit 0
[root@iZ2zee88b1mcsq6mmf7w95Z scripts]# ./sh04.sh 
please input(y/n):y
yes
[root@iZ2zee88b1mcsq6mmf7w95Z scripts]# ./sh04.sh 
please input(y/n):N
no
[root@iZ2zee88b1mcsq6mmf7w95Z scripts]# 

注: 特别要注意[] 中的空格 必须写啊

2.多重、复杂条件判断式

#一个简单条件判断
if [条件判断式]; then
    当条件成立后,可以进行的命令工作内容;
else
    当条件不成立时,执行的命令;
fi 

# 多个条件判断
if [条件判断式1]; then
    当条件1成立后,可以进行的命令工作内容;
elif [条件判断式2]; then
    当条件2成立时,执行的命令;
elif ......

else
    当前面的所有条件都不成立的时候,执行这个;
fi 

将上面的改成这个格式:

[root@iZ2zee88b1mcsq6mmf7w95Z scripts]# nl sh05.sh 
     1  #!/bin/bash
     2  # Program:
     3  #   This program is hello world!
     4  #

     5  read -p "please input(y/n):" result

     6  if [ "$result" == "Y" ] || [ "$result" == "y" ] ; then
     7      echo "yes"
     8  elif [ "$result" == "N" ] || [ "$result" == "n" ] ; then
     9          echo "no"
    10  else
    11      echo "error "
    12  fi


    13  exit 0
[root@iZ2zee88b1mcsq6mmf7w95Z scripts]# ./sh05.sh 
please input(y/n):y
yes
[root@iZ2zee88b1mcsq6mmf7w95Z scripts]# ./sh05.sh 
please input(y/n):n
no
[root@iZ2zee88b1mcsq6mmf7w95Z scripts]# ./sh05.sh 
please input(y/n):a
error 
[root@iZ2zee88b1mcsq6mmf7w95Z scripts]# 

(二)、case…esac

类似于switch…case


case $变量名称 in #关键字是case 还有变量前有$
"第一个变量内容")
程序段
;;
"第二个变量内容")
程序段
;;
"第三个变量内容")
程序段
;;
*) #类似于default
exit 1
;;
esac

eg:

[root@iZ2zee88b1mcsq6mmf7w95Z scripts]# nl sh07.sh 
     1  #!/bin/bash
     2  # Program:
     3  #   This program is hello world!
     4  #
     5  typeset -l result
     6  read -p "please input(y/n):" result

     7  #result=echo $result | tr 'A-Z' 'a-z'
     8  echo $result
     9  case $result in
    10      "y" )
    11          echo "yes"
    12          ;;
    13      "n")
    14          echo "no"
    15               ;;
    16      *)
    17          echo "error "
    18          exit 1
    19          ;;
    20  esac


    21  exit 0
[root@iZ2zee88b1mcsq6mmf7w95Z scripts]# ./sh07.sh 
please input(y/n):Y
y
yes
[root@iZ2zee88b1mcsq6mmf7w95Z scripts]# 

六、function 功能

函数不需要太多解释了,直接上用法吧!

function 函数名(){

}

举个例子吧:

[root@iZ2zee88b1mcsq6mmf7w95Z scripts]# cat sh08.sh 
#!/bin/bash
# Program:
#   This program is hello world!
#

function  printfMe(){
    echo -n "your choice is: " #-n表示不断行继续在同一行显示
}

echo "This program will print your selection!"
case $1 in
    "one")
    printfMe; echo $1 | tr 'a-z' 'A-Z'
    ;;
        "two") 
        printfMe; echo $1 | tr 'a-z' 'A-Z'
        ;;

        "three") 
        printfMe; echo $1 | tr 'a-z' 'A-Z'
        ;;
    *)
    printfMe; echo "shit";;

esac

exit 0

[root@iZ2zee88b1mcsq6mmf7w95Z scripts]# ./sh08.sh one
This program will print your selection!
your choice is: ONE
[root@iZ2zee88b1mcsq6mmf7w95Z scripts]# ./sh08.sh two
This program will print your selection!
your choice is: TWO
[root@iZ2zee88b1mcsq6mmf7w95Z scripts]# ./sh08.sh Three
This program will print your selection!
your choice is: shit
[root@iZ2zee88b1mcsq6mmf7w95Z scripts]# 

函数的内置变量和shell script的内置变量差不多。

$0 $1 $2…来代替,这里就不演示了。传参的方式就是 函数名 参数1 参数2 ...

七、循环(loop)

(一)、while do done, until do done 不定循环

#条件成立时进行循环
while [ 判断式 ] 
do  #do是循环的开始
    程序段
done #done是循环的的结束
#条件成立时就终止循环,否则继续执行
util [ 判断式 ] 
do  #do是循环的开始
    程序段
done #done是循环的的结束

(二)、for…do..done(for循环)

for var in con1 con2 con3...
do
    程序段
done
#第一次循环 $var的值是con1 第二次是con2 依次类推...
#数值处理
for ( (初始值;限制值;执行步长) )
do
    程序段
done

写一个i++的例子吧

s=0
for ( (i=1; i<=100; i=i+1) )
do
    s=s+1
done

八、shell script的追踪和调试

利用bash的相关参数调试

格式:sh [-nvx] test.sh

参数:

  • -n:不执行test.sh,仅检查语法错误;
  • -v:在执行test之前,将test的内容输出到屏幕上
  • -x:将使用到的test的内容显示到屏幕上。

注:

1. 介绍shell中字符串大小写转换的方式

  1. typeset

    有两个选项 -l 代表小写 -u 代表大写。

    用法:

    typeset -u name

    name=’asdasdas’

    echo $name

    typeset -l ame

    ame=’asdasdas’

    echo $ame

    结果:

    ASDASDAS

    asdasdas

  2. 利用表达式

    echo ‘hello’ | tr ‘a-z’ ‘A-Z’

    echo ‘HELLO’ | tr ‘A-Z’ ‘a-z’

    结果:

    HELLO

    hello

你可能感兴趣的:(Linux)