Shell脚本编程——上

Shell简介

Shell本身是一个用C语言编写的程序,它是用户使用Unix/Linux的桥梁,用户的大部分工作都是通过Shell完成的。Shell既是一种命令语言,又是一种程序设计语言。作为命令语言,它交互式地解释和执行用户输入的命令;作为程序设计语言,它定义了各种变量和参数,并提供了许多在高级语言中才具有的控制结构,包括循环和分支。

它虽然不是Unix/Linux系统内核的一部分,但它调用了系统核心的大部分功能来执行程序、建立文件并以并行的方式协调各个程序的运行。因此,对于用户来说,shell是最重要的实用程序,深入了解和熟练掌握shell的特性极其使用方法,是用好Unix/Linux系统的关键。

可以说,shell使用的熟练程度反映了用户对Unix/Linux使用的熟练程度。

Shell有两种执行命令的方式:
交互式(Interactive):解释执行用户的命令,用户输入一条命令,Shell就解释执行一条。
批处理(Batch):用户事先写一个Shell脚本,其中有很多条命令,让Shell一次把这些命令执行完,而不必一条一条地敲命令。

Shell脚本和编程语言很相似,也有变量和流程控制语句,但Shell脚本是解释执行的,不需要编译,Shell程序从脚本中一行一行读取并执行这些命令,相当于一个用户把脚本中的命令一行一行敲到Shell提示符下执行。

start

helloworld

1、新建helloworld.sh,vim helloworld.sh内容为:

1
2
#!/bin/bash
echo "Hello World !"

#! 是一个约定的标记,它告诉系统这个脚本需要什么解释器来执行,即使用哪一种Shell。echo命令用于向窗口输出文本。

2、添加执行权限
chmod +x helloworld.sh

3、执行脚本
./helloworld.sh

PS:输入gg跳到首行,.,$d,表示从当前行到末行全部删除掉。或者,1,$d,表示从首行到末行全部删除掉。

echo

echo是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
#!/bin/bash

# 显示转义字符
echo "\"It is a test\""

# 显示变量
name="VoidKing"
echo "Welcome, $name"

# 变量与其它字符相连时需要使用大括号
month=8
echo "${month}-1-2009"

# 显示换行
echo -e "OK!\n"
echo "It is a test"

# 显示不换行
echo -e "OK!\c"
echo "It is a test"

# 显示结果重定向至文件
echo "It is a test" > myfile

# 原样输出字符串
echo '$name\"'

# 显示命令执行结果
echo `date`

printf

printf 命令用于格式化输出, 是echo命令的增强版。它是C语言printf()库函数的一个有限的变形,并且在语法上有些不同。

注意:printf 由 POSIX 标准所定义,移植性要比 echo 好。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#!/bin/bash

# format-string为双引号
printf "%d %s\n" 1 "abc"

# 单引号与双引号效果一样
printf '%d %s\n' 1 "abc"

# 没有引号也可以输出
printf %s abcdef

# 一个格式多个参数
printf %s abc def
printf "%s\n" abc def
printf "%s %s %s\n" a b c d e f g h i j

# %s默认为空,%d默认为0
printf "%s and %d \n"

# 如果以%d的格式来显示字符串,那么会有警告,并且默认置为 0
printf "always prints %s,%d\n" Hello Shell

交互

使用 read 命令从 stdin 获取输入并赋值给 PERSON 变量,最后在 stdout 上输出。

1
2
3
4
5
#!/bin/bash

echo "What is your name?"
read PERSON
echo "Hello, $PERSON"

重定向

1
2
3
4
5
6
7
8
9
10
11
12
#!/bin/bash

# stdout重定向到file
ls -l > file
ls -l >> file

# stdout和stderr合并后重定向到myfile
ls -l > myfile 2>&1
ls -l >> myfile 2>&1

# 屏蔽 stdout 和 stderr
ls -l > /dev/null 2>&1
1
2
3
4
5
6
#!/bin/bash

cat << EOF
My name is VoidKing.
I'm good at programming.
EOF

包含脚本

1
url="http://www.voidking.com"
1
2
3
4
5
6
#!/bin/bash

. ./helloworld.sh
source ./helloworld.sh
. ./url.sh
echo $url

变量

基本变量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#!/bin/bash

# 定义变量
your_name="voidking"
your_age=25

# 显示变量
echo -e "your name is ${your_name} \n welcome to shell world"
echo "your age is ${your_age}"

your_email="voidking@qq.com"

# 设置your_email为只读变量
readonly your_email

echo "your email is $your_email"

your_address="中国吉林长春"

# 删除变量
unset your_address

注意,变量名和等号之间不能有空格,这可能和我们熟悉的所有编程语言都不一样。
shell里没有多行注释,只能每一行加一个#号。

上面的脚本中,我们使用了一些中文。在CentOS7.2中,如果出现乱码,那么,我们需要添加CentOS7.2的中文支持。
locale,显示LANG=C。

vim /etc/locale.conf,修改locale.conf如下:

1
2
3
4
LANG="zh_CN.UTF-8"
LANGUAGE="zh_CN.UTF-8:zh_CN.UTF-8:zh_CN"
SUPPORTED="zh_CN.UTF-8:zh_CN:zh:en_US.UTF-8:en_US:en"
SYSFONT="lat0-sun16"

locale,显示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
LANG=zh_CN.UTF-8
LC_CTYPE="zh_CN.UTF-8"
LC_NUMERIC="zh_CN.UTF-8"
LC_TIME="zh_CN.UTF-8"
LC_COLLATE="zh_CN.UTF-8"
LC_MONETARY="zh_CN.UTF-8"
LC_MESSAGES="zh_CN.UTF-8"
LC_PAPER="zh_CN.UTF-8"
LC_NAME="zh_CN.UTF-8"
LC_ADDRESS="zh_CN.UTF-8"
LC_TELEPHONE="zh_CN.UTF-8"
LC_MEASUREMENT="zh_CN.UTF-8"
LC_IDENTIFICATION="zh_CN.UTF-8"
LC_ALL=

特殊变量

1
2
3
4
5
6
7
8
9
#!/bin/bash

echo "Process ID: $$"
echo "File Name: $0"
echo "First Parameter: $1"
echo "Second Parameter: $2"
echo "Quoted Values: $@"
echo "Quoted Values: $*"
echo "Total Number of Parameters: $#"

变量替换

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#!/bin/bash

echo ${var:-"Variable is not set"}
echo "1 - Value of var is ${var}"

echo ${var:="Variable is not set"}
echo "2 - Value of var is ${var}"

unset var
echo ${var:+"This is default value"}
echo "3 - Value of var is $var"

var="Prefix"
echo ${var:+"This is default value"}
echo "4 - Value of var is $var"

echo ${var:?"Print this message"}
echo "5 - Value of var is ${var}"

命令替换

1
2
3
4
5
6
7
8
#!/bin/bash

DATE=`date`
echo "Date is $DATE"
USERS=`who | awk '{print $1}'`
echo "Logged in user are $USERS"
UP=`date ; uptime`
echo "Uptime is $UP"

字符串

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
#!/bin/bash

# 单引号字符串中的变量无效,任何字符都会原样输出
# 单引号字串中不能出现单引号(对单引号使用转义符后也不行)
str='this is a string'

# 双引号里可以有变量,可以出现转义符
str="Hello, I know your are \"$your_name\"! \n"


# 拼接字符串
your_name="voidking"
greeting="hello, "$your_name" !"
greeting_1="hello, ${your_name} !"
echo $greeting $greeting_1

# 获取字符串长度
string="abcd"
echo ${#string}

# 提取子字符串
string="alibaba is a great company"
echo ${string:1:4}

# 查找子字符串
string="alibaba is a great company"
echo `expr index "$string" is`

数组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#!/bin/sh

name[0]="VoidKing0"
name[1]="VoidKing1"
name[2]="VoidKing2"
echo "Index0: ${name[0]}"
echo "Index1: ${name[1]}"

echo "All names: ${name[*]}"
echo "All names: ${name[@]}"

age=(24 25 26)
age[2]=25

# 取得数组元素的个数
name_length=${#name[@]}
age_length=${#age[*]}
echo "name_length: $name_length,age_length: $age_length"

# 取得数组单个元素的长度
lengthn=${#name[0]}
echo "Index0 length: $lengthn"

源码分享

https://github.com/voidking/shell.git

书签

Linux Shell脚本教程:30分钟玩转Shell脚本编程
http://c.biancheng.net/cpp/shell/

0%