首页 > 代码库 > 30分钟让你学会shell脚本

30分钟让你学会shell脚本

                       Shell脚本编程入门

什么是shell脚本

实例

看个例子:

 

#!/bin/sh

cd ~

mkdir shell_tut

cd shell_tut

for ((i=0; i<10; i++)); do

 touch test_$i.txt

done

示例解释

 1行:指定脚本解释器,这里是用/bin/sh做解释器的

 2行:切换到当前用户的home目录

 3行:创建一个目录shell_tut 4行:切换到shell_tut目录

 5行:循环条件,一共循环10

 6行:创建一个test_110.txt文件

 7行:循环体结束

 cd, mkdir, touch都是系统自带的程序,一般在/bin或者/usr/bin目录下。for, do, donesh脚本语言的关键字。

 

Shellshell脚本的概念

    shellshell脚本的概念 shell是指一种应用程序,这个应用程序提供了一个界面,用户通过这个界面访问操作系统内核的服务。Ken Thompsonsh是第一种Unix ShellWindows Explorer是一个典型的图形界面Shell

shell脚本(shell script),是一种为shell编写的脚本程序。业界所说的shell通常都是指shell脚本,但读者朋友要知道,shellshell script是两个不同的概念。由于习惯的原因,简洁起见,本文出现的“shell编程”都是指shell脚本编程,不是指开发shell自身(如Windows Explorer扩展开发)。

 

Bash

bash BashBourne shell的替代品,属GNU Project,二进制文件路径通常是/bin/bash。业界通常混用bashsh、和shell,比如你会经常在招聘运维工程师的文案中见到:熟悉Linux Bash编程,精通Shell编程。

 

编译型语言,只要有解释器,也可以用作脚本编程,如C shell是内置的(/bin/csh),Java有第三方解释器JshellAda有收费的解释器AdaScript

 

如下是一个PHP Shell Script示例(假设文件名叫test.php):

 #!/usr/bin/php

<?php

for ($i=0; $i<10;$i++)

          echo $i . "\n";

执行:

/usr/bin/php test.php

或者:

chmod +x test.php

./text.php

 

 

编写

打开文本编辑器,新建一个文件,扩展名为shsh代表shell),扩展名并不影响脚本执

行,见名知意就好,如果你用phpshell 脚本,扩展名就用php好了。

 

输入一些代码,第一行一般是这样:

 

 

#!/bin/bash

#!/usr/bin/php

 

#!”是一个约定的标记,它告诉系统这个脚本需要什么解释器来执行

 

运行

 

运行Shell脚本有两种方法:

 

  作为可执行程序

 

chmod +x test.sh

./test.sh

 

 

   注意,一定要写成./test.sh,而不是test.sh,运行其它二进制的程序也一样,

直接写test.shlinux系统会去PATH里寻找有没有叫test.sh的,

而只有/bin, /sbin, /usr/bin/usr/sbin等在PATH里,

你的当前目录通常不在PATH里,所以写成test.sh是会找不到命令的,要用./test.sh告诉系统说,就在当前目录找。

 

通过这种方式运行bash脚本,第一行一定要写对,好让系统查找到正确的解释器。

 

作为解释器参数

 

这种运行方式是,直接运行解释器,其参数就是shell脚本的文件名,如:

 /bin/sh test.sh

/bin/php test.php

 

这种方式运行的脚本,不需要在第一行指定解释器信息,写了也没用。

 

变量

 

定义变量

 

 定义变量时,变量名不加美元符号($),如:

 

 your_name="qinjx"

 

   注意,变量名和等号之间不能有空格,这可能和你熟悉的所有编程语言都不一样。

 

   除了显式地直接赋值,还可以用语句给变量赋值,如:

 

   for file in `ls /etc`

 

使用变量

 

  使用一个定义过的变量,只要在变量名前面加美元符号即可,如:

 

  your_name="qinjx"

echo $your_name

echo ${your_name}

 

 

变量名外面的花括号是可选的,加不加都行,加花括号是为了帮助解释器识别变量的边界,比如下面这种情况:

 

 for skill in Ada Coffe Action Java do

 echo "I am good at ${skill}Script"

 done

 

 

如果不给skill变量加花括号,写成echo "I am good at $skillScript",解释器就会把$skillScript当成一个变量

其值为空),代码执行结果就不是我们期望的样子了。

 

推荐给所有变量加上花括号,这是个好的编程习惯。IntelliJ IDEA编写shell script时,IDE就会提示加花括号。

 

 

重定义变量

已定义的变量,可以被重新定义,如:

 your_name="qinjx"

echo $your_name

 

your_name="alibaba"

echo $your_name

 

这样写是合法的,但注意,第二次赋值的时候不能写$your_name="alibaba",使用变量的时候才加美元符。

 

 

注释

 #”开头的行就是注释,会被解释器忽略。

 

  多行注释  

  sh里没有多行注释,只能每一行加一个#号。就像这样:

#--------------------------------------------

# 这是一个自动打ipa的脚本,基于webfrogsipa-build书写:https://github.com/webfrogs/xcode_shell/blob/master/ipa-build

# 功能:自动为etao ios app打包,产出物为14个渠道的ipa

# 特色:全自动打包,不需要输入任何参数

#--------------------------------------------

 

##### 用户配置区 开始 #####

#

#

# 项目根目录,推荐将此脚本放在项目的根目录,这里就不用改了

# 应用名,确保和XcodeProduct下的target_name.app名字一致

# ##### 用户配置区 结束 #####

 

如果在开发过程中,遇到大段的代码需要临时注释起来,过一会儿又取消注释,怎么办呢?每一行加

#符号太费力了,可以把这一段要注释的代码用一对花括号括起来,定义成一个函数,没有地方调用

这个函数,这块代码就不会执行,达到了和注释一样的效果。

 

 

字符串

 

  字符串是shell编程中最常用最有用的数据类型(除了数字和字符串,也没啥

其它类型好用了,哈哈),字符串可以用单引号,也可以用双引号,也可以不用

引号。单双引号的区别跟PHP类似。

 

 

单引号

  str=‘this is a string‘

 

单引号字符串的限制:

 

 单引号里的任何字符都会原样输出,单引号字符串中的变量是无效的

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

 

 

双引号

 your_name=‘qinjx‘

str="Hello, I know your are \"$your_name\"! \n"

 

 

  双引号里可以有变量

  双引号里可以出现转义字符

 

 

字符串操作

 

 拼接字符串

 

your_name="qinjx"

greeting="hello, "$your_name" !"

greeting_1="hello, ${your_name} !"

 

echo $greeting $greeting_1

 

获取字符串长度

 

 string="abcd"

echo ${#string} #输出:4

 

  提取子字符串

 

   string="alibaba is a great company"

echo ${string:1:4} #输出:liba

 

 

  查找子字符串

 string="alibaba is a great company"

echo `expr index "$string" is`#输出:8,这个语句的意思是:找出单词is在这名话中的位置

 

数组

 

管道

 

条件判断

 

流程控制

 

  JavaPHP等语言不一样,sh的流程控制不可为空,如:

 

 

  <?php

if (isset ($_GET["q"])) {

    search(q);

}

else {

      //do nothing

}

 

sh/bash里可不能这么写,如果else分支没有语句执行,就不要写这个else

 

还要注意,sh里的if [ $foo -eq 0 ],这个方括号跟Java/PHPif后面的圆括号大不相同,它是一个可执行程序(和cd, ls, grep一样),相不到吧?在CentOS上,它在/usr/bin目录下: ll /usr/bin/[

 

 

ll /usr/bin/[ -rwxr-xr-x. 1 root root 33408 622 2012 /usr/bin/[

 

正因为方括号在这里是一个可执行程序,方括号后面必须加空格,不能写成if [$foo -eq 0]

 

if else

if

 

if condition

then

    command1

    command2

    ...

    commandN

fi

 

写成一行(适用于终端命令提示符):

 

if `ps -ef | grep ssh`; then echo hello; fi

 

末尾的fi就是if倒过来拼写,后面还会遇到类似的

 

if else

   

   if condition  

then  

    command1

    command2

     ...

    commandN

else

    command

fi

 

 

if else-if else

   if condition1

then

   command1

elif condition2

   command2

else

   commandN

fi

 

 

for while

 

在开篇的示例里演示过了:

  

    for var in ite for

m1 item2 ... itemN

do

    command1

    command2

     ...

    commandN

done

 

 写成一行:

 for var in item1 item2 ... itemN; do command1; command2done;

 

C风格的for

   for (( EXP1; EXP2; EXP3 ))

do

   command1

   command2

   command3

done

 

while

     

     while condition

do

     command

done

 

 

无限循环

 

   while :

do

   command

done

 

   或者

   

    while true

do

    command

done

 

 

   或者

 

  for (( ; ; ))

 

 

until

    

    until condition

do

    command

done

 

 

case

 

    case "${opt}" in

    "Install-Puppet-Server" )

         install_master $1

      exit

      ;;

      

     "Install-Puppet-Client" ) install_client $1

      exit

       ;;

      

     "Config-Puppet-Server" )

      config_puppet_master

      exit

      ;;

 

      "Config-Puppet-Client" )

      config_puppet_client

      exit

      ;;

 

      "Exit" )

      exit

      ;;

       * )

 

      echo "Bad option, please choose again"

      esac

 

 

case的语法和C family语言差别很大,它需要一个esac(就是case反过来)作为结束标记,每个case分支用右圆括号,用两个分号表示break

 

 

函数

 

定义

 

调用

 

文件包含

 

 可以使用source.关键字,如:

 

    source ./function.sh

  . ./function.sh

 

   bash里,source.是等效的,他们都是读入function.sh的内容并执行其内容(类似PHP里的include),为了更好的可移植性,推荐使用第二种写法。

 

包含一个文件和在执行一个文件一样,也要写这个文件的路径,不能光写文件名,比如上述例子中:

    . ./function.sh

 

   不可以写作:

   

   . function.sh

 

   如果function.sh是用户传入的参数,如何获得它的绝对路径呢?方法是:

 

     real_path=`readlink -f $1`#$1是用户输入的参数,如function.sh

. $real_path

 

 

用户输入

 

执行脚本时传入

 

脚本运行中输入

 

select菜单

 

Stdinstdout

 

常用的命令

 

 

sh脚本结合系统命令便有了强大的威力,在字符处理领域,有grepawksed三剑客,grep负责找出特定的行,awk能将行拆分成多个字段,

sed则可以实现更新插入删除等写操作。

 

 ps

 

 查看进程列表

 

 grep

 

 排除grep自身

 

 查找与target相邻的结果

 

 awk

 

 sed

 

 插入

 

 替换

 

 删除

 

 xargs

 

 curl

 

 

 

 

 

 

 

 

 


本文出自 “浅吻着你额头︶ㄣ紫玫瑰” 博客,请务必保留此出处http://1298411894.blog.51cto.com/11494198/1844235

30分钟让你学会shell脚本