Shell脚本编程30分钟入门

发表于 4年以前  | 总阅读数:1653 次

Shell脚本编程30分钟入门

什么是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_0…9.txt文件
  • 第7行:循环体结束

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

shell和shell脚本的概念

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

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

环境

shell编程跟java、php编程一样,只要有一个能编写代码的文本编辑器和一个能解释执行的脚本解释器就可以了。

OS

当前主流的操作系统都支持shell编程,本文档所述的shell编程是指Linux下的shell,讲的基本都是POSIX标准下的功能,所以,也适用于Unix及BSD(如Mac OS)。

Linux

Linux默认安装就带了shell解释器。

Mac OS

Mac OS不仅带了sh、bash这两个最基础的解释器,还内置了ksh、csh、zsh等不常用的解释器。

Windows上的模拟器

windows出厂时没有内置shell解释器,需要自行安装,为了同时能用grep, awk, curl等工具,最好装一个cygwin或者mingw来模拟linux环境。

脚本解释器

sh

即Bourne shell,POSIX(Portable Operating System Interface)标准的shell解释器,它的二进制文件路径通常是/bin/sh,由Bell Labs开发。

本文讲的是sh,如果你使用其它语言用作shell编程,请自行参考相应语言的文档。

bash

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

在CentOS里,/bin/sh是一个指向/bin/bash的符号链接:

    [root@centosraw ~]# ls -l /bin/*sh
    -rwxr-xr-x. 1 root root 903272 Feb 22 05:09 /bin/bash
    -rwxr-xr-x. 1 root root 106216 Oct 17  2012 /bin/dash
    lrwxrwxrwx. 1 root root      4 Mar 22 10:22 /bin/sh -> bash

但在Mac OS上不是,/bin/sh和/bin/bash是两个不同的文件,尽管它们的大小只相差100字节左右:

    iMac:~ wuxiao$ ls -l /bin/*sh
    -r-xr-xr-x  1 root  wheel  1371648  6 Nov 16:52 /bin/bash
    -rwxr-xr-x  2 root  wheel   772992  6 Nov 16:52 /bin/csh
    -r-xr-xr-x  1 root  wheel  2180736  6 Nov 16:52 /bin/ksh
    -r-xr-xr-x  1 root  wheel  1371712  6 Nov 16:52 /bin/sh
    -rwxr-xr-x  2 root  wheel   772992  6 Nov 16:52 /bin/tcsh
    -rwxr-xr-x  1 root  wheel  1103984  6 Nov 16:52 /bin/zsh

高级编程语言

理论上讲,只要一门语言提供了解释器(而不仅是编译器),这门语言就可以胜任脚本编程,常见的解释型语言都是可以用作脚本编程的,如:Perl、Tcl、Python、PHP、Ruby。Perl是最老牌的脚本编程语言了,Python这些年也成了一些linux发行版的预置解释器。

编译型语言,只要有解释器,也可以用作脚本编程,如C shell是内置的(/bin/csh),Java有第三方解释器Jshell,Ada有收费的解释器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
    ./test.php

如何选择shell编程语言

熟悉 vs 陌生

如果你已经掌握了一门编程语言(如PHP、Python、Java、JavaScript),建议你就直接使用这门语言编写脚本程序,虽然某些地方会有点啰嗦,但你能利用在这门语言领域里的经验(单元测试、单步调试、IDE、第三方类库)。

新增的学习成本很小,只要学会怎么使用shell解释器(Jshell、AdaScript)就可以了。

简单 vs 高级

如果你觉得自己熟悉的语言(如Java、C)写shell脚本实在太啰嗦,你只是想做一些备份文件、安装软件、下载数据之类的事情,学着使用sh,bash会是一个好主意。

shell只定义了一个非常简单的编程语言,所以,如果你的脚本程序复杂度较高,或者要操作的数据结构比较复杂,那么还是应该使用Python、Perl这样的脚本语言,或者是你本来就已经很擅长的高级语言。因为sh和bash在这方面很弱,比如说:

  • 它的函数只能返回字串,无法返回数组
  • 它不支持面向对象,你无法实现一些优雅的设计模式
  • 它是解释型的,一边解释一边执行,连PHP那种预编译都不是,如果你的脚本包含错误(例如调用了不存在的函数),只要没执行到这一行,就不会报错

环境兼容性

如果你的脚本是提供给别的用户使用,使用sh或者bash,你的脚本将具有最好的环境兼容性,perl很早就是linux标配了,python这些年也成了一些linux发行版的标配,至于mac os,它默认安装了perl、python、ruby、php、java等主流编程语言。

第一个shell脚本

编写

打开文本编辑器,新建一个文件,扩展名为sh(sh代表shell),扩展名并不影响脚本执行,见名知意就好,如果你用php写shell 脚本,扩展名就用php好了。

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

    #!/bin/bash
    #!/usr/bin/php

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

运行

运行Shell脚本有两种方法:

作为可执行程序

    chmod +x test.sh
    ./test.sh

注意,一定要写成./test.sh,而不是test.sh,运行其它二进制的程序也一样,直接写test.sh,linux系统会去PATH里寻找有没有叫test.sh的,而只有/bin, /sbin, /usr/bin,/usr/sbin等在PATH里,你的当前目录通常不在PATH里,所以写成test.sh是会找不到命令的,要用./test.sh告诉系统说,就在当前目录找。

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

这里的"系统",其实就是shell这个应用程序(想象一下Windows Explorer),但我故意写成系统,是方便理解,既然这个系统就是指shell,那么一个使用/bin/sh作为解释器的脚本是不是可以省去第一行呢?是的。

作为解释器参数

这种运行方式是,直接运行解释器,其参数就是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的脚本,基于webfrogs的ipa-build书写:https://github.com/webfrogs/xcode_shell/blob/master/ipa-build

    # 功能:自动为etao ios app打包,产出物为14个渠道的ipa包
    # 特色:全自动打包,不需要输入任何参数
    #--------------------------------------------

    ##### 用户配置区 开始 #####
    #
    #
    # 项目根目录,推荐将此脚本放在项目的根目录,这里就不用改了
    # 应用名,确保和Xcode里Product下的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`#输出:3,这个语句的意思是:找出字母i在这名话中的位置,要在linux下运行,mac下会报错

更多

参见本文档末尾的参考资料中Advanced Bash-Scripting Guid Chapter 10.1

数组

管道

条件判断

流程控制

和Java、PHP等语言不一样,sh的流程控制不可为空,如:

    <?php
    if (isset($_GET["q"])) {
        search(q);
    }
    else {
        //do nothing
    }

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

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

    ll /usr/bin/[
    -rwxr-xr-x. 1 root root 33408 6月  22 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

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

    for var in item1 item2 ... itemN
    do
        command1
        command2
        ...
        commandN
    done

写成一行:

    for var in item1 item2 ... itemN; do command1; command2… done;

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菜单

stdin和stdout

常用的命令

sh脚本结合系统命令便有了强大的威力,在字符处理领域,有grep、awk、sed三剑客,grep负责找出特定的行,awk能将行拆分成多个字段,sed则可以实现更新插入删除等写操作。

ps

查看进程列表

grep

排除grep自身

查找与target相邻的结果

awk

sed

插入

替换

删除

xargs

curl

综合案例

参考资料

 相关推荐

刘强东夫妇:“移民美国”传言被驳斥

京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。

发布于:6月以前  |  808次阅读  |  详细内容 »

博主曝三大运营商,将集体采购百万台华为Mate60系列

日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。

发布于:6月以前  |  770次阅读  |  详细内容 »

ASML CEO警告:出口管制不是可行做法,不要“逼迫中国大陆创新”

据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。

发布于:6月以前  |  756次阅读  |  详细内容 »

抖音中长视频App青桃更名抖音精选,字节再发力对抗B站

今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。

发布于:6月以前  |  648次阅读  |  详细内容 »

威马CDO:中国每百户家庭仅17户有车

日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。

发布于:6月以前  |  589次阅读  |  详细内容 »

研究发现维生素 C 等抗氧化剂会刺激癌症生长和转移

近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。

发布于:6月以前  |  449次阅读  |  详细内容 »

苹果据称正引入3D打印技术,用以生产智能手表的钢质底盘

据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。

发布于:7月以前  |  446次阅读  |  详细内容 »

千万级抖音网红秀才账号被封禁

9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...

发布于:6月以前  |  445次阅读  |  详细内容 »

亚马逊股东起诉公司和贝索斯,称其在购买卫星发射服务时忽视了 SpaceX

9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。

发布于:6月以前  |  444次阅读  |  详细内容 »

苹果上线AppsbyApple网站,以推广自家应用程序

据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。

发布于:6月以前  |  442次阅读  |  详细内容 »

特斯拉美国降价引发投资者不满:“这是短期麻醉剂”

特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。

发布于:6月以前  |  441次阅读  |  详细内容 »

光刻机巨头阿斯麦:拿到许可,继续对华出口

据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。

发布于:6月以前  |  437次阅读  |  详细内容 »

马斯克与库克首次隔空合作:为苹果提供卫星服务

近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。

发布于:6月以前  |  430次阅读  |  详细内容 »

𝕏(推特)调整隐私政策,可拿用户发布的信息训练 AI 模型

据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。

发布于:6月以前  |  428次阅读  |  详细内容 »

荣耀CEO谈华为手机回归:替老同事们高兴,对行业也是好事

9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。

发布于:6月以前  |  423次阅读  |  详细内容 »

AI操控无人机能力超越人类冠军

《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。

发布于:7月以前  |  423次阅读  |  详细内容 »

AI生成的蘑菇科普书存在可致命错误

近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。

发布于:7月以前  |  420次阅读  |  详细内容 »

社交媒体平台𝕏计划收集用户生物识别数据与工作教育经历

社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”

发布于:7月以前  |  411次阅读  |  详细内容 »

国产扫地机器人热销欧洲,国产割草机器人抢占欧洲草坪

2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。

发布于:6月以前  |  406次阅读  |  详细内容 »

罗永浩吐槽iPhone15和14不会有区别,除了序列号变了

罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。

发布于:6月以前  |  398次阅读  |  详细内容 »
 相关文章
如何查看docker镜像里的文件 4年以前  |  5185次阅读
Shell语法快速入门 5年以前  |  2884次阅读
Shell命令在后台运行程序 5年以前  |  2821次阅读
Shell脚本编程30分钟入门 4年以前  |  1654次阅读
 目录