Linux_Shell

一、Shell 种类与归属

  1. Unix与Linux常见的Shell脚本解释器有bash,sh,csh,ksh等(PS: bash 完全兼容sh)
    • bash : linux 默认的shell
    • sh : unix 默认的shell
    • csh : 是linux中比较大的内核,命令指向/bin/tcsh的,可以认为csh为tcsh
    • ksh : 兼容商业发行版

  2. shell 本身是用C语言编写的程序,它是用户操作unix/linux的桥梁,用户的大部分工作是通过shell来完成的

    shell 既是一种命令语言,也是一种程序设计语言,他有自己的编程结构,变量,参数和很多高级语言中的控制语句与循环语句

    shell 两种交互: ① 交互型:用户输入一条,shell就执行一条 ② 批处理:用户写多条命令存在于一个shell脚本中,shell一次性完成

二、Shell 与其他语言区别

  1. shell 是一种解释性语言(运行时编译),而C、C++、Java 等高级语言是编译型语言(程序运行前,预编译)
  2. shell 相对于其他高级语言对文件处理更为方便快捷,但是运行的效率不如编译后的高级语言

三、不建议使用 Shell 场景

  1. 资源密集型的任务,尤其在需要考虑效率时(比如,排序,hash等等)。
  2. 需要处理大任务的数学操作,尤其是浮点运算,精确运算,或者复杂的算术运算(这种情况一般使用C++或FORTRAN 来处理)。
  3. 有跨平台(操作系统)移植需求(一般使用C 或Java)。
  4. 复杂的应用,在必须使用结构化编程的时候(需要变量的类型检查,函数原型,等等)。
  5. 对于影响系统全局性的关键任务应用。
  6. 对于安全有很高要求的任务,比如你需要一个健壮的系统来防止入侵、破解、恶意破坏等等。
  7. 项目由连串的依赖的各个部分组成。
  8. 需要大规模的文件操作。
  9. 需要多维数组的支持。
  10. 需要数据结构的支持,比如链表或数等数据结构。
  11. 需要产生或操作图形化界面 GUI。
  12. 需要直接操作系统硬件。
  13. 需要 I/O 或socket 接口。
  14. 需要使用库或者遗留下来的老代码的接口。
  15. 私人的、闭源的应用(shell 脚本把代码就放在文本文件中,全世界都能看到)。

四、简单 Shell 示例

1
2
3
4
5
6
7
8
9
10
11
12
13
[root@hadoop09-linux tmp]# cat firstShell.sh          # .sh 是shell文件类型
#!/bin/bash                             # bash文件头 #!作为约定标记,告诉系统需要什么解释器运行
# Description: shell simple example #                       # 简述该shell文件功能作用,这里输出一句话
 
echo welcom to use shell                     # shell执行命令
[root@hadoop09-linux tmp]# sh firstShell.sh          # 使用sh命令执行shell
welcom to use shell
[root@hadoop09-linux tmp]# ll                  # 查看shell运行权限
total 4
-rw-r--r--. 1 root root 76 Sep  7 18:22 firstShell.sh      # 可以看到所有用户组都没有运行权限
[root@hadoop09-linux tmp]# chmod a+x firstShell.sh      # 赋予权限
[root@hadoop09-linux tmp]# ./firstShell.sh            # ./执行shell
welcom to use shell                         # 输出结果

  再看一个例子:

  功能:让用户选择Y 或N,如果使用者输入n 或N 时,就显示“Oh,interrupt”,如果不是Y/y/N/n 之内的其他字节,就显示“I don't know what your choice is”
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
[root@hadoop09-linux tmp]# cat secondShell.sh
#!/bin/bash
#------------------------------------------------
#当运行一个脚本的时候,这个脚本会让用户选择Y 或N ,
#如果使用者输入Y 或y 时,就显示“OK,continue”
#如果使用者输入n 或N 时,就显示“Oh,interrupt”
#如果不是Y/y/N/n 之内的其他字节,就显示“I don't know what your choice is”
#------------------------------------------------
 
echo "please input Y/y or N/n"
read words
if [ "$words" = "Y" -o "$words" = "y" ];then
    echo "OK,continue"
elif [ "$words" = "N" -o "$words" = "n" ];then
    echo "Oh,interrupt"
else
    echo "I don't know what your choice is"
fi
[root@hadoop09-linux tmp]# sh secondShell.sh
please input Y/y or N/n
y
OK,continue
[root@hadoop09-linux tmp]# sh secondShell.sh
please input Y/y or N/n
n
Oh,interrupt
[root@hadoop09-linux tmp]# sh secondShell.sh
please input Y/y or N/n
a
I don't know what your choice is

五、Shell 注释

  shell 中没有多行注释,需要注释时只需在行首加上#

六、Shell 变量

  变量类型

  1. 局部变量:局部变量在脚本或命令中定义,仅在当前shell实例中有效,其他shell启动的程序不能访问局部变量
  2. 环境变量:所有的程序,包括shell启动的程序,都能访问环境变量,有些程序需要环境变量来保证其正常运行。必要的时候shell脚本也可以定义环境变量
  3. shell变量:shell变量是由shell程序设置的特殊变量。shell变量中有一部分是环境变量,有一部分是局部变量,这些变量保证了shell的正常运行
  4. 特殊变量:$0;$1,$2,$3...$9;$#;$*;$@;$?;$$
1
2
3
4
5
6
7
8
9
10
11
12
13
14
[root@hadoop09-linux tmp]# cat thirdShell.sh
#!/bin/bash
#Description...#
 
num=6                            # 定义变量,有点像javascript
echo "num:$num"               # 没加{},{}可加可不加
num=8                            # 重新给变量赋值,前面赋值将被覆盖
echo "num:${num}"            # 加上{} 有时解释器会解释成 "num:$num" 加上花括号是为了方便系统识别变量边界,为变量加上{}是个好习惯 
unset num                        # 删除变量
echo "num:${num}"     
[root@hadoop09-linux tmp]# sh thirdShell.sh
num:6
num:8
num:                 # 删除变量后,变量为空

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[root@hadoop09-linux tmp]# cat fourthShell.sh
#!/bin/bash
echo "File Name: $0"                      # $0 当前shell文件名
echo "First Parameter : $1"                  # $1 shell文件后跟的第一个参数
echo "First Parameter : $2"                  # $2 shell文件后跟的第二个参数
echo "Quoted Values: $@"                     # $@ 传递给shell的所有参数,参数作为最小单位输出
echo "Quoted Values: $*"                     # $* 传递给shell的所有参数 与$@有细微不同,参数作为整体输出
echo "Total Number of Parameters : $#"             # $# 传递给shell的参数个数
echo "result : $?"                        # $? 上一个执行的命令结果-->0:成功;1:失败 有时一些命令返回其它值,表示不同类型的错误
echo "shell pid : $$"                      # $$ 当前shell进程ID
[root@hadoop09-linux tmp]# sh fourthShell.sh num1 num2
File Name: fourthShell.sh
First Parameter : num1
First Parameter : num2
Quoted Values: num1 num2
Quoted Values: num1 num2
Total Number of Parameters : 2
result : 0
shell pid : 3055

七、Shell 替换

  1. 特殊字符替换:使用 -e 替换字符串中的转移字符:\\(反斜杠);\a(警报);\b(退格键);\f(翻页);\n(换行);\r(换行);\t(水平制表符tab);\v(垂直制表符)
  2. 命令替换:预先执行命令 `command`(反引号)
  3. 变量替换:类似java三元运算符,或sql中替换函数,例 ${var:-word}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
[root@hadoop09-linux tmp]# cat fifthShell.sh
#!/bin/bash
num=10
echo "this num is ${num} \n"              # 未加 -e 转义,将输出原本模样
echo -e "this num is ${num} \n"            # 将\n转义,将换行
Date=`date`                        # 预先执行date命令,将结果赋给Date
echo "this date is ${Date}"
str="string"
echo "this str is ${str}"                # str原本模样
echo "this str is ${str:+"newString"}"         # 表示str如果存在,则将newString替换输出
unset str                          # 删除变量str
echo "this str is ${str:-"newString"}"         # 表示str如果不存在或为空,则将newString替换输出
echo "this str is ${str:?"str is empty"}"       # 表示str如果不存在或为空,则报错,shell停止,报错内容为替换内容
[root@hadoop09-linux tmp]# sh fifthShell.sh
this num is 10 \n
this num is 10
 
this date is Wed Sep  7 19:48:16 PDT 2016
this str is string
this str is newString
this str is newString
fifthShell.sh: line 13: str: str is empty

八、Shell 运算符 (PS: if [] 中 [ ... ] 与 test ... 作用一样)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
算数运算符 (最常使用运算工具:expr 2 + 2 ;注意运算时空格一定要有)
  num=`expr 2 + 2`
  num=`expr 4 - 2`
  num=`expr 4 \* 2`          # 乘法需要加\转义
  num=`expr 4 / 2`
  num='expr 4 % 2'
  num=$num1
  if [ $num1 == $num2 ]
  if [ $num1 != $num2 ]  
关系运算符
  if [ $str1 -eq $str2 ]       # 是否相等
  if [ $str1 -ne $str2 ]           # 是否不相等
  if [ $str1 -gt $str2 ]            # 是否大于>
  if [ $str1 -lt $str2 ]         # 是否小于<
  if [ $str1 -ge $str2 ]           # 是否大于等于>=
  if [ $str1 -le $str2 ]            # 是否小于等于<=
布尔运算符
  if [ $str1 != $str2 ]                                   # !非运算
  if [ $str1 -eq $str2 -a $str3 -eq $str4 ]      # -a and
  if [ $str1 -eq $str2 -o $str3 -eq $str4 ]      # -o or
字符串运算符
  if [ $str1 = $str2 ]                                        # 判断两个字符串是否相等
  if [ $str1 != $str2 ]                                       # 判断两个字符串是否不相等
  if [ -z $str1 ]                                             # 判断字符串长度是否为零,为0则true
  if [ -n $str1 ]                                                 # 判断字符串长度是否不为零,不为0则true
  if [ $str1 ]                                                     # 判断字符串是否不为空,不为空则true
文件测试运算符
  if [ -r $file ]                                                  # 文件是否可读
  if [ -w $file ]                                                 # 文件是否可写
  if [ -x $file ]                                                  # 文件是否可执行
  if [ -f $file ]                                                   # 是否是普通文件
  if [ -d $file ]                                                  # 是否是目录目录文件
  if [ -b $file ]                                                  # 是否是块设备文件
  if [ -c $file ]                                                  # 是否是字符设备文件
  if [ -s $file ]                                                  # 文件是否有内容
  if [ -e $file ]                                                  # 文件(包括各类型文件)是否存在

九、Shell 数据

  1. 字符串
    • 单引号
      • 单引号内$无效,原文本输出
      • 单引号内不能再出现单引号
    • 双引号
      • 双引号内可以有变量
      • 可以出现转义字符
      • 双引号内可以再次出现双引号
    • 拼接字符串
      • "words"$str
      • "words$str"
      • "words,"$str""
      • "words,${str}"
    • 获取字符串长度
      • ${#str}
    • 提取字符串
      • ${str:1:4}
    • 查找字符串 
      • str="hello linux"
      • echo `expr index "${str}"  ll`                 # 注意其中的双引号不能去掉
  2. 数组
    • 定义数组
      • arrays=(v1 v2 v3 v4 v5)                         # 以空格分隔
      • arrays[0]=v1                                         # 也可以单个赋值
    • 读取数组
      • $arrays/${arrays}                              # 默认读取第一个值
      • ${arrays[n]}                                         # 读取第n+1个值
      • ${arrays[*]}/${arrays[@]}                     # 读取数组中所有值
    • 获取数组长度
      • ${#arrays[n]}                                       # 读取单个值的长度
      • ${#arrays[*]}/${#arrays[@]}                 # 读取整个数组长度

十、Shell echo与printf命令

1
2
3
4
5
6
7
8
9
10
11
12
echo
  显示转义字符                                                  # "\"words...\""
  显示变量                                                          
  显示换行                                                           # 转义换行需要加 -e
  显示不换行                                                         # 转义不换行需要加 -e
  显示结果重定向到文件                                           # "words..." > file 注:file若不存在则新建并录入
  原样输出                                                            # 使用单引号原样输出
  显示命令执行结果                                                 # echo `date`
printf
  格式化输出,是echo的增强版,类似C语言中的printf 需要注意的是:printf并不会自动换行,需要自行加上\n
  格式:printf format-string data
  printf "%s %s \n" kk ll mm                                # 每隔一个单词格式化一次%s 代表一个单词,和awk命令中的print有些区别,awk有自己的格式化方式

十一、Shell if else 语句

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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
fi
 
if [ expression ];then
   Statement(s) to be executed if expression is true
else
   Statement(s) to be executed if expression is false
fi
 
if [ expression ];then
   Statement(s) to be executed if expression is true
elif [ expression2 ];then
   Statement(s) to be executed if expression2 is true  
else
   Statement(s) to be executed if expression1 and expression2 all false
fi

十二、Shell while 语句

1
2
3
4
while command
do
   Statement(s) to be executed if command is true
done

十三、Shell until 循环

1
2
3
4
until command                                              # 与while 判断正好相反
do
   Statement(s) to be executed until command is true
done

十四、Shell for 循环

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
for 变量 in 列表
do
    command1
    command2
    ...
    commandN
done
<br># 示例1 : 遍历1~5,并输出
for loop in 1 2 3 4 5
do
    echo "The value is: $loop"
done
<br># 示例2 : 遍历当前用户家目录下的所有以.bash开头的文件
for FILE in $HOME/.bash*
do
   echo $FILE
done

十五、Shell case 语句

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
case 值 in
模式1)
    command1
    command2
    command3
    ;;
模式2
    command1
    command2
    command3
    ;;
*)
    command1
    command2
    command3
    ;;
esac
 
# 示例1
echo 'Input a number between 1 to 4'
echo 'Your number is:\c'
read aNum
case $aNum in
    1)  echo 'You select 1'
    ;;
    2)  echo 'You select 2'
    ;;
    3)  echo 'You select 3'
    ;;
    4)  echo 'You select 4'
    ;;
    *)  echo 'You do not select a number between 1 to 4'
    ;;
esac
 
# 示例2
option="${1}"
case ${option} in
   -f) FILE="${2}"
      echo "File name is $FILE"
      ;;
   -d) DIR="${2}"
      echo "Dir name is $DIR"
      ;;
   *)
      echo "`basename ${0}`:usage: [-f file] | [-d directory]"
      exit 1 # Command to come out of the program with status 1
      ;;
esac

十七、Shell 跳出循环

  1. break 允许跳出所有循环

1
2
3
4
5
6
7
8
9
10
11
12
13
#!/bin/bash
while :
do
    echo -n "Input a number between 1 to 5: "
    read aNum
    case $aNum in
        1|2|3|4|5) echo "Your number is $aNum!"
        ;;
        *) echo "You do not select a number between 1 to 5, game is over!"
            break
        ;;
    esac
done

  PS:break n 表示跳出第n层循环

1
2
3
4
5
6
7
8
9
10
11
12
13
#!/bin/bash
for var1 in 1 2 3
do
   for var2 in 0 5
   do
      if [ $var1 -eq 2 -a $var2 -eq 0 ]
      then
         break 2
      else
         echo "$var1 $var2"
      fi
   done
done

2.continue 允许跳出当前循环体

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/bin/bash
while :
do
    echo -n "Input a number between 1 to 5: "
    read aNum
    case $aNum in
        1|2|3|4|5) echo "Your number is $aNum!"
        ;;
        *) echo "You do not select a number between 1 to 5!"
            continue
            echo "Game is over!"
        ;;
    esac
done

  运行发现echo "Game is over" 永远不会被执行

  同break一样,continue后面跟一个数字表示跳出第几层循环

1
2
3
4
5
6
7
8
9
10
11
12
#!/bin/bash
NUMS="1 2 3 4 5 6 7"
for NUM in $NUMS
do
   Q=`expr $NUM % 2`
   if [ $Q -eq 0 ]
   then
      echo "Number is an even number!!-"$NUM
      continue 2
   fi
   echo "Found odd number"
done

十八、Shell 函数/函数参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
function_name () {
    list of commands
    [ return value ]
}
# 或
function function_name () {
    list of commands
    [ return value ]
}
 
# 示例1
Hello () {                                                                       #方法定义
   echo "Url is http://xxx/xxx/"
}
Hello                                                                              #方法调用,必须先定义方法
 
# 示例2 带return
funWithReturn(){
    echo "The function is to get the sum of two numbers..."
    echo -n "Input first number: "
    read aNum
    echo -n "Input another number: "
    read anotherNum
    echo "The two numbers are $aNum and $anotherNum !"
    return $(($aNum+$anotherNum))
}
funWithReturn
# Capture value returnd by last command
ret=$?
echo "The sum of two numbers is $ret !"
 
# 示例3 嵌套
number_one () {
   echo "Url_1 is http://xxx/xxx/"
   number_two
}
number_two () {
   echo "Url_2 is http://xxx/xxx/"
}
number_one

  删除方法定义

1
$unset .f function_name

  函数传参

1
2
3
4
5
6
7
8
9
10
11
#!/bin/bash
funWithParam(){
    echo "The value of the first parameter is $1 !"               # 1
    echo "The value of the second parameter is $2 !"              # 2
    echo "The value of the tenth parameter is $10 !"              # 10
    echo "The value of the tenth parameter is ${10} !"             # 34
    echo "The value of the eleventh parameter is ${11} !"            # 73
    echo "The amount of the parameters is $# !"                  # 参数个数 12     
    echo "The string of the parameters is $* !"                  # 传递给函数的所有参数 1 2 3 4 5 6 7 8 9 34 73 
}
funWithParam 1 2 3 4 5 6 7 8 9 34 73

十九、Shell 输入输出重定向

  1. 输出重定向 

1
2
3
4
5
6
7
8
9
10
11
12
13
$ command > file
 
# 示例
$ who > users          # 文件不存在则新建,存在则覆盖
 
$ command >> file
 
# 示例
$ echo line 2 >> users     # 文件不存在则新建,存在则追加
$ cat users
line 1
line 2
$

  2. 输入重定向

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
$ command < file
 
# 示例
$ wc -l < users
2
$
 
$ command << delimiter
    document
delimiter
 
# 示例1
$wc -l << EOF
    This is a simple lookup program
    for good (and bad) restaurants
    in Cape Town.
EOF
3
$
 
# 示例2
cat << EOF
This is a simple lookup program
for good (and bad) restaurants
in Cape Town.
EOF
 
# 示例3
filename=test.txt
vi $filename <<EndOfCommands
i
This file was created automatically from
a shell script
^[
ZZ
EndOfCommands

  如果执行某个命令,却不想让结果输出来,可以重定向到/dev/null

1
$ command > /dev/null

二十、Shell 文件包含

  像其他语言一样,shell中也可以包含外部脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
. filename
#或
source filename
 
# 示例1
 
# 脚本1 1.sh 不必有执行权限
#!/bin/bash
url="http://xxx/xxx/xxx.html"
 
#脚本2 2.sh 必须有执行权限
#!/bin/bash
. ./1.sh
echo $url
posted @   eRrsr  阅读(490)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示