Shell是一种编程语言, 它像其它编程语言如: C, Java, Python等一样也有变量/函数/运算符/if语句/循环控制/… 但在开始之前, 我想先理清Shell语言与Shell之间的关系.

Shell与Shell语言

上面说了Shell是一种编程语言但你可能也听说过: sh/bash/csh/zsh/…它们也叫Shell, 实际上这里所说的Shell是一种应用程序, 它负责解释执行你编写的Shell脚本, Mac默认就自带了sh/bash/csh/zsh/tcsh/ksh, 你可以这样查看cat /etc/shells
不同的shell的用法基本相同, 但有些shell提供了一些新特性, 比如我现在在用的就是zsh, 更多zsh的内容可以去看这篇文章

第一个Shell脚本

#! /bin/sh
echo "hello shell!"

依国际惯例这里以在终端里打印一句hello shell!开始, 第一行的#!是一个约定标记, 它告诉脚本这段脚本需要什么解释器来执行. 第二行的echo命令则负责向屏幕上输出一句话.

如何运行

运行shell程序有3种方法:

  1. chmod +x使文件具有可执行权限, 直接运行
  2. 直接调用解释器, 将脚本文件作为参数传入 (比如bash hi.sh)
  3. 使用source(也可用 . 代替)执行文件

通常情况下, 最方便的方式就是方式1, 通过方式1执行你需要在脚本第一行写好这段脚本由哪个解释器来解释, 而通过方式2来执行则没有这个限制, 写了也没用.
除此之外方式1与方式2执行命令就没有区别了, 但方式3执行的方式与前两种都不同:

使用source执行shell脚本时, 不会创建子进程, 而是在父进程中直接执行!

这里不作更多解释, 感兴趣的同学可以去参考Linux Shell编程从入门到精通这本书的第一章的相关部分.

变量

和其它语言一样Shell中也有变量, 而且更简单, 但有一些比较特殊的地方.

  1. Shell中的变量只有字符串这一种类型
  2. Shell中变量名与变量值没有长度限制
  3. Shell的变量也允许比较操作和整数操作, 只要变量中的字符串为数字

定义变量

variable_name=ghui

需要注意: = 两边不能加空格, 当赋值语句包含空格时请加引号(单引号/双引号均可)比如:

variable_name="ghui's blog"

Shell中的变量可以分为两种类型:

  1. 局部变量 (定义变量时在前面加local修饰符)
  2. 全局变量 (定义变量时不加任何修饰符)

与其它语言一样局部变量的可见范围是代码块或函数内, 全局变量在全局范围内可见.看个简单的例子:

#! /bin/sh
num=111 #全局变量

func1()
{
  local num=222 #局部变量
  echo $num
}

echo "before---$num"
func1
echo "after---$num"

输出:

before---111
222
after---111

使用变量

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

name=ghui
echo $name
echo ${name} #{} 为了帮助解释器识别变量边界, 非必须

在使用变量时还有一个地方需要注意, 请看下面的例子:

#! /bin/sh
str='abc'
echo "1 print $str"
echo '2 print $str'

输出:

1 print abc
2 print $str

即:
被双引号括起来的变量会发生变量替换, 单引号不会

注释

Shell中注释使用#, 而且它不支持多行注释.

常用的字符串操作

字符串拼接

name="shell"
sayHi="hello, "$name" !"
sayHi2="hello, ${name} !"
echo $sayHi $sayHi2

注意: 上面说的单双引号引起的变量替换问题

获得字符串长度

string="abcd"
echo ${#string} #输出:4

截取字符串

str="hello shell"
echo ${str:2}  #输出: llo shell
echo ${string:1:3} #输出:ell

更多关于字符串的操作可以看这个

if/else流程控制

基本语法结构:

if condition
then
	 do something
elif condition
then
	do something
elif condition
then
	do something
else
	do something
fi

其中, elif语句和else语句非必须的.看个例子:

#! /bin/sh
a=1
if [ $1=$a ]
then
	echo "you input 1"
elif [ $1=2 ]
then
	echo "you input 2"
else
	#do nothing
	echo " you input $1"
fi

很简单, 不过这里有两个地方需要注意, 如果某个条件下的执行体为空, 则你就不能写这个条件 即下面这样会报错:

if condition
then
	#do nothing
elif condition
then
	# do nothing
#or
else
	#do nothing

另外, [ ] 两边一定要加空格, 下面这样都会报错:

if [$a=$b]
#or
if [ $a=$b]
#or
if [$a=$b ]

只有这样if [ $a=$b ]才是对的.
注意: 实际上这里的[]test命令的一种形式, [是系统的一个内置命令,存在路径是/bin/[,它是调用test命令的标识, 右中括号是关闭条件判断的标识, 因此下面的两个测试语句是等效的:

if test "2>3"
then
	...
fi

if [ "2>3" ]
then
	…
fi

[]之外, shell语言中还有几种其它括号, 比如: 单小括号/双小括号/双中括号/… , 不同的括号有不同的用法, 更多关于shell中, 括号的用法可以看看这个

switch流程控制

当条件较多时, 可以选择使用switch语句, shell中的switch语句的写法和其它语言还是有些不同的, 基本结构如下:

case expression in
	pattern1)
		do something... ;;
	pattern2)
		do something... ;;
	pattern2)
		do something... ;;
	...
esac

看个例子:

#! /bin/sh
input=$1
case $input in
        1 | 0)
        str="一or零";;
        2)
        str="二";;
        3)
        str="三";;
        *)
        str=$input;;
esac
echo "---$str"

这个例子会根据你执行此脚本时传入的参数不同在屏幕上输出不同的值, 其中第一个case 1 | 0代表逻辑或.
NOTE:

  1. ;;相当于其它语言中的break
  2. 每个pattern之后记得加)
  3. 最后记得加esac (即反的case)

for循环

基本结构:

for name [in list]
do
	...
done

其中,[]括起来的 in list, 为可选部分, 如果省略in list则默认为in "$@", 即你执行此命令时传入的参数列表.
看个例子:

for file in *.txt
do
	open $file
done

遍历当前目录下的所有txt文件, 并依次打开.

while循环

基本结构:

while condition
do
	do something...
done

看个例子:

#! /bin/sh
i=0
while ((i<5));
do
	((i++))
	echo "i=$i"
done

输出:

i=1
i=2
i=3
i=4
i=5

NOTE: 你可能需要去了解一下(())的用法

until循环

基本结构

until condition
do
	do something...
done

看个例子:

#! /bin/sh
i=5
until ((i==0))
do
	((i--))
	echo "i=$i"
done

输出:

i=4
i=3
i=2
i=1
i=0

跳出循环

shell中也支持break跳出循环, continue跳出本次循环.用法与C, Java中相同

函数

要定义一个函数, 可以使用下面两种形式:

function funcname()
{
	do something
}

或者

funcname ()
{
	do something
}

看个例子

#! /bin/sh
# ad.sh 计算sum
add()
{
	let "sum=$1+$2"
	return $sum
}

add $1 $2
echo "sum=$?"

输入

ad 1 2

输出

sum=3

其中, $?在shell中保存的是上一条命令的返回值

NOTE:

  1. 函数必须先定义后使用
  2. 如果在函数中使用exit会退出脚本, 如果想退回到原本函数调用的地方, 则可使用return

向脚本传递参数

先shell脚本传递参数, 非常简单, 只需要在你执行命令的后面跟上即可, 看个例子:

#! /bin/sh
# test.sh
echo "$# parameters";
echo "$@";
echo "$0"
echo "$1"

输入:

test.sh 11 22

输出:

2 parameters
11 22
test.sh
11

后记

之所以要写这篇博客, 有以下几个原因:

  1. 想总结一下shell编程中的关键知识点, 方便日后查看.
  2. 想通过shell优化一下我的hexo写作及博客管理流程, 目前相关脚本已完成, 待我下一篇博客分享给大家, 如果你也是在用Hexo写博客, 相信对你会很有用, 尽请期待! 已经发布
  3. 可以看的出这里总结的都是最关键的知识点, 还有很多这里并没有说. 是因为我觉得刚开始学习一个东西没必要太计较一些细节/琐碎的东西, 掌握好大致知识框架, 然后在大家编写具体的脚本时, 遇到具体问题, 再去google寻找即可.

参考

Shell脚本编程总结及速查手册的更多相关文章

  1. LINUX SHELL脚本攻略笔记[速查]

    Linux Shell脚本攻略笔记[速查] 资源 shell script run shell script echo printf 环境变量和变量 pgrep shell数学运算 命令状态 文件描述 ...

  2. 【链接】LINUX SHELL脚本攻略笔记[速查]

    LINUX SHELL脚本攻略笔记[速查]

  3. Shell脚本编程(一)

    shell 脚本编程(一) 1 . shell 的作用 Shell的作用是解释执行用户的命令,用户输入一条命令,Shell就解释执行一条,这种方式称为交互式(Interactive),Shell还有一 ...

  4. SHELL脚本编程的常识和VI常用技巧

    来源:http://mprc.pku.edu.cn/mentors/training/TrainingCourses/material/ShellProgramming.HTM#_Toc3751808 ...

  5. 程序员 & 设计师都能用上的 75 份速查手册

    分享75份开发人员和设计师会用到的速查手册,由 vikas 收集整理,包括:jQuery.HTML.HTML5.CSS.CSS3.JavaScript.Photoshop .git.Linux.Jav ...

  6. CUDA 7.0 速查手册

    Create by Jane/Santaizi 03:57:00 3/14/2016 All right reserved. 速查手册基于 CUDA 7.0 toolkit documentation ...

  7. 《Linux命令行与shell脚本编程大全 第3版》

    第一部分 Linux 命令行 第1章  初识Linux she1.1   什么是Linux 21.1.1 深入探究Linux 内核 31.1.2 GNU 工具 61.1.3 Linux 桌面环境 81 ...

  8. Docker常用命令速查手册(华贵铂金版)

    原创声明:作者:Arnold.zhao  博客园地址:https://www.cnblogs.com/zh94 Docker常用命令速查手册 搜索仓库镜像 docker search nginx 获取 ...

  9. Linux命令行与Shell脚本编程大全

    快来参加<Linux命令行与Shell脚本编程大全>学习吧,提升技能,展示自我. 点击链接即可进入学习:https://s.imooc.com/WTmCO6H 课程亮点适合零基础读者,从零 ...

随机推荐

  1. MVC5 ModelBinder

    MVC5 ModelBinder 什么是ModelBinding ASP.NET MVC中,所有的请求最终都会到达某个Controller中的某个Action并由该Action负责具体的处理和响应.为 ...

  2. windows store app Lifecycle

    1.Activated 2.Suspended 3.Resumed 4.Terminated 对应的 js代码: (function () { "use strict"; WinJ ...

  3. bug - colorWithPatternImage:

    // 在ios5之前, 再通过以下方法设置背景时, 有闪屏bug self.view.backgroundColor = [UIColor colorWithPatternImage:<#(no ...

  4. 【转载】Java 升级到jdk7后DbVisualizer 6 启动空指针的处理方案

    将JDK从6升级到了7(或从其他电脑移植DBV文件夹后),每当启动DbVisualizer 6的时候都会报空指针异常 在官网上找到了相关的方案,如下: In the DbVisualizer inst ...

  5. Collection和Collections的区别

    Collection 是集合类的上级接口,继承它的接口主要有set和list.Collections 是针对集合类的一个帮助类,他提供一系列静态方法实现对各种集合的搜索,排序,线程安全化等操作.

  6. apache+tomcat 负载均衡

    说明:本篇不面向无开发基础的人员,所以不会有软件下载,jdk安装等步骤.比较久远的东西了...... 1.系统环境 win7-64.jdk 2.软件列表: apache_2.2.24-x64-no-s ...

  7. CSS3制作下拉菜单

    导航菜单其实是没有什么可说的,制作方法到处可见,今天这个案例本来不只是一个导 航,还有一个搜索表单的,可是为了偷懒,把搜索表单部分去掉了,就变成了一个CSS3 制作的下拉菜单.在这个导航中主要两点,一 ...

  8. Python/Numpy大数据编程经验

    Python/Numpy大数据编程经验 1.边处理边保存数据,不要处理完了一次性保存.不然程序跑了几小时甚至几天后挂了,就啥也没有了.即使部分结果不能实用,也可以分析程序流程的问题或者数据的特点.   ...

  9. POJ 3349 Snowflake Snow Snowflakes(哈希)

    http://poj.org/problem?id=3349 题意 :分别给你n片雪花的六个角的长度,让你比较一下这n个雪花有没有相同的. 思路:一开始以为把每一个雪花的六个角的长度sort一下,然后 ...

  10. 用PYTHON硬写SOCKET

    这个文章的系列很有意思,练练~~: http://python.jobbole.com/82763/ :) 第一步,最简单的SERVER和CLIENT.感觉和写JAVA,C的最简单的一样一样的,,看来 ...