什么是Shell?  

  Shell是Linux系统的用户界面,提供了用户与内核进行交互操作的一种接口。它接收用户输入的命令并把它送入内核去执行。
  实际上Shell是一个命令解释器,它解释由用户输入的命令并且把它们送到内核。不仅如此,Shell有自己的编程语言用于对命令的编辑,它允许用户编写由shell命令组成的程序。Shell编程语言具有普通编程语言的很多特点,比如它也有循环结构和分支控制结构等,用这种编程语言编写的Shell程序与其他应用程序具有同样的效果。Shell既是一种命令语言,又是一种程序设计语言。
 
  Linux 中的 shell 有很多类型,其中最常用的几种是: Bourne shell (sh)、C shell (csh) 和 Korn shell (ksh), 各有优缺点。Bourne shell 是 UNIX 最初使用的 shell,并且在每种 UNIX 上都可以使用, 在 shell 编程方面相当优秀,但在处理与用户的交互方面做得不如其他几种shell。
  Linux 操作系统缺省的 shell 是Bourne Again shell,它是 Bourne shell 的扩展,简称 Bash,与 Bourne shell 完全向后兼容,并且在Bourne shell 的基础上增加、增强了很多特性。Bash放在/bin/bash中,它有许多特色,可以提供如命令补全、命令编辑和命令历史表等功能,它还包含了很多 C shell 和 Korn shell 中的优点,有灵活和强大的编程接口,同时又有很友好的用户界面。
 

简单的shell脚本

  新建一个 test.sh, vi 输入下面内容

#!/bin/bash 
# This is a very simple example
echo Hello World

  1. #! 这一行表明,不管用户选择的是那种交互式shell,该脚本需要使用bash shell来运行。

  2. # 就是 BASH 程序的注释,在 BASH 程序中从“#”号(注意:后面紧接着是“!”号的除外)开始到行尾的多有部分均被看作是程序的注释。
  
  输入 $ bash test.sh 或 $ sh tesh.sh 可以运行
 

变量

  任何编程语言都会用到变量。你可以使用下面的语句来定义一个变量:

  并按下面的格式来引用这个变量:

  $X

  更具体的说,$X表示变量X的值。关于语义方面有如下几点需要注意:

  • 等于号两边不可以有空格!例如,下面的变量声明是错误的 :
X = hello
  • 在展示的例子中,引号并不都是必须的。只有当变量值包含空格时才需要加上引号。例如:
X=hello world # 错误
X="hello world" # 正确

  

  关于单引号和双引号:

  基本上来说,变量名会在双引号中展开,单引号中则不会。

  如果你不需要引用变量值,那么使用单引号可以很直观的输出你期望的结果。 

  也可以在双引号中使用转义字符 

#!/bin/bash
# this is simple example
/bin/echo -n '$USER=' # -n选项表示阻止echo换行,mac下echo -n不生效改为/bin/echo -n
echo "$USER"
echo "\$USER=$USER" # 该命令等价于上面的两行命令

  输出结果为:

  
  
  使用大括号保护变量:
  假设你想打印变量X的值,并在值后面紧跟着打印”abc”。如下写法没有任何输出。
X=ABC
echo "$Xabc"

  这是由于shell以为我们想要打印变量Xabc的值,实际上却没有这个变量。为了解决这种问题可以用大括号将变量名包围起来,从而避免其他字符的影响。

X=ABC
echo "${X}abc"

  输出结果为:

  

  

  在执行中展开变量:

#!/bin/bash
LS="ls"
AL="-al"
echo "$HOME"
echo "$LS $AL $HOME"
$LS $AL $HOME 

  执行结果如下: 

  

 

条件判断if/then/elif

  条件判断语法如下:

if condition
then 
   statement1
   statement2
   ......
fi

  当指定条件不满足时,可以通过else来指定其他执行动作。

if condition
then 
   statement1
   statement2
   ......
else 
   statement3
fi

  当if条件不满足时,可以添加多个elif来检查其他条件是否满足。

if condition1
then 
   statement1
   statement2
   ......
elif condition2
then
   statement3   
   statement4
   ......
elif condition3
then
   statement5
   statement6
   ......
fi

 

Test命令与操作符

  条件判断中的命令几乎都是test命令。test根据测试条件通过或失败来返回true或false(更准确的说是返回0或非0值)。

  test 命令用于检查某个条件是否成立,它可以进行数值、字符和文件三个方面的测试。

test operand1 operator operand2

  通常这么简写:

[ operand1 operator operand2 ]

  例:

#!/bin/bash
X=3
Y=4
empty_string=""

if [ $X -lt $Y ]
then
    echo "X=${X},which is smaller than Y=${Y}"
fi

if [ -n "$empty_string" ]
then
    echo "this is not empty String"
else
    echo "this is empty Stirng"
fi

  输出结果:

  

 

  Test操作符简介

  数值测试

参数说明
-eq 等于则为真
-ne 不等于则为真
-gt 大于则为真
-ge 大于等于则为真
-lt 小于则为真
-le 小于等于则为真

  字符串测试

参数说明
= 等于则为真
!= 不相等则为真
-z 字符串 字符串的长度为零则为真
-n 字符串 字符串的长度不为零则为真

  文件测试

参数说明
-e 文件名 如果文件存在则为真
-r 文件名 如果文件存在且可读则为真
-w 文件名 如果文件存在且可写则为真
-x 文件名 如果文件存在且可执行则为真
-s 文件名 如果文件存在且至少有一个字符则为真
-d 文件名 如果文件存在且为目录则为真
-f 文件名 如果文件存在且为普通文件则为真
-c 文件名 如果文件存在且为字符型特殊文件则为真
-b 文件名 如果文件存在且为块特殊文件则为真


 

循环

  循环结构允许我们执行重复的步骤或者在若干个不同条目上执行相同的程序。Bash中有下面两种循环

  • for 循环
  • while 循环

   For 循环

  直接举个例子

#!/bin/bash
for X in red green blue
do
    echo "$X"
done

  输出结果:

  

  

  For循环会遍历空格分开的条目。注意,如果某一项含有空格,必须要用引号引起来

#!/bin/bash
colour1="red"
colour2="light blue"
colour3="dark green"
for X in "$colour1" $colour2" $colour3"
do
    echo "$X"
done

  如果写成这样那么,根据空格分开输出结果为:

  

  这个例子说明,除非你确认变量中不会包含空格,否则最好都用引号将变量保护起来。

 

  在For循环中使用通配符

  如果shell解析字符串时遇到*号,会将它展开为所有匹配的文件名。当且仅当目标文件与号展开后的字符串一致才会匹配成功。例如,单独的*号展开为当前目录的所有文件,中间以空格分开(包含隐藏文件)。

  所以:

  •   列出当前目录下的所有文件和目录。

      echo *

  •   列出所有的jpeg图片格式的文件。

      echo *.jpg

  •   列出home目录中public_html目录下的所有jpeg文件。

      echo ${HOME}/public_html/*.jpg

 

  正是由于这种特性,使得我们可以很方便的来操作目录和文件,尤其是和for循环结合使用时,更是便利。

#!/bin/bash
for X in *.sh
do
    grep -L 'if' "$X"
done

  打印出当前目录下所有不包含if字段的.sh文件。输出结果如下:

  

 

  while循环

  当给定条件为真值时,while循环会重复执行。例如:

#!/bin/bash
X=0
while [ "$X" -lt 20 ]
do
    echo "$X"
    X=$((X+1))
done

  X=$((X+1)) 也可以写成 X=$(expr "$X" + 1),其输出结果如下:

  

  这样导致这样的疑问: 为什么bash不能使用C风格的for循环呢?

  for (X=1,X<10; X++)

  这也跟bash自身的特性有关,之所以不允许这种for循环是由于:bash是一种解释性语言,因此其运行效率比较低。也正是由于这个原因,高负荷迭代是不允许的。

 

命令替换

  Bash shell有个非常好用的特性叫做命令替换。允许我们将一个命令的输出当做另一个命令的输入。比如你想要将命令的输出赋值给变量X,你可以通过变量替换来实现。

  有两种命令替换的方式:大括号扩展和反撇号扩展。

  大括号扩展: $(commands) 会展开为命令commands的输出结果。并且允许嵌套使用,所以commands中允许包含子大括号扩展。

  反撇好扩展:将commands扩展为命令commands的输出结果。不允许嵌套。

#/bin/bash
file="$(ls)"
web_file=`ls -al test.sh`
echo "$file"
echo "$web_file"
X=`expr 3 * 2 + 1`
echo "$X" 

  输出结果为:

   

  $()替换方式的优点不言自明:非常易于嵌套。并且大多数bourne shell的衍生版本都支持(POSIX shell 或者更好的都支持)。

  不过,反撇号替换更简单明了,即使是最基本的shell它也提供了支持(任意版本的#!/bin/sh都可以)。

 

参考:http://blog.jobbole.com/85183/

 

 

 

 

posted on 2017-11-15 14:55  dyppp  阅读(307)  评论(0)    收藏  举报