Shell编程
Shell编程
1. shell简明教程
1.1 基本命令
1 |
|
#!是约定标记,表示使用什么解释器执行。
注释
以#开头的行就是注释,会被解释器忽略。sh里没有多行注释,只能每一行加一个#号。1
2
3# --------
# 这是注释块
# --------
打印输出
1 | echo arg |
echo 后单引号不能转义里面的字符,双引号可有可无。
printf:用于格式化输出,echo的增强版。不默认换行
1 | printf format-string [arguments...] |
C语言printf()和shell的printf的不同
- shell printf的不用括号。
- format-string 可以没有引号,但最好加上。
- 如果arguments比格式化参数更多,格式化参数可以重用。
- arguments使用空格隔开。
read: 命令行从设备读入内容1
2
3
4
5
echo "what is your name"
read NAME #输入到NAME
echo "Hello, $NAME"
变量
定义变量1
variableName="value" #变量名和=之间不能有空格
首个字符必须为字母(a-z,A-Z)。
中间不能有空格,可以使用下划线(_)。
不能使用标点符号。
不能使用bash里的关键字(可用help命令查看保留关键字)。
注意:变量中间不能有空格,如果手误写错(例如 var = test),刚好要使用rm -rf $var/删除这个目录,实际删除的是/!
使用变量1
2
3
4for skill in C PHP Python Java
do
echo "I am good at ${skill}Script" #这里需要加上花括号
done
可以把变量变为只读或者删除1
2
3
4url="http://www.baidu.com"
readonly url #变量为只读
url2="http://www.netease.com"
unset url2 #删除变量,但是不能删除只读变量
变量类型
- 局部变量:仅在当前shell实例中有效,其他shell启动程序无法访问局部变量
- 环境变量:所有的程序,包括shell启动的程序都能访问环境变量,必要时shell也可以访问环境变量
- shell变量:shell变量有shell设置的特殊变量。一部分是环境变量,一部分是局部变量。
特殊变量
变量 | 含义 |
---|---|
$0 |
当前脚本文件名 |
$n |
传递给脚本的参数 |
$# |
传递给脚本的参数个数 |
$* |
传递给脚本的所有参数 |
$@ |
传递给脚本或函数的所有参数。被双引号(“”)包含时,与$* 不同 |
$? |
上个命令的退出状态或函数的返回值 |
$$ |
当前shell进程的ID。对于Shell脚本,就是这些脚本所在进程的id |
$*
1.2 运算符
Bash 支持很多运算符,包括算数运算符、关系运算符、布尔运算符、字符串运算符和文件测试运算符。
算数运算符
原生bash不支持简单的数学运算,但是可以运用awk和expr,expr比较常用expr
是一款表达式计算工具,完成求值工作。1
2
3
4
5
a=10
b=20
var=`expr $a + $b` #不是单引号,是ESC下面的
echo $var
注意:
- 表达式和运算符之间要有空格
- *替代*
- 注意引号
算数运算符列表
1 | 运算符 说明 举例 |
关系运算符
关系运算符只支持数组,不支持字符串,除非字符串值为数字。1
2
3
4
5
6if [ $a -eq $b ]
then
echo "$a eq $b :a is equal to b"
else
echo "$a -eq $b :a is not equal to b"
fi
- if后面直到直到then前面的分号结束都有空格。
关系运算符列表
1 | 运算符 说明 |
布尔运算符
1 | 运算符 说明 |
1 | if [ 3 -gt 2 -a 4 -lt 5 ] |
字符串运算符列表
1 | 运算符 说明 举例 |
文件测试运算符
1 |
|
文件测试运算符列表
1 | 操作符 说明 举例 |
1.3 字符串和数组
字符串
单引号和双引号的区别
- 双引号里有变量,单引号里原样输出
- 双引号有转义字符,单引号原样输出
- 单引号中不能有单引号
获取字符串长度1
2str='i love you'
echo ${#str}
截取字符串1
2
3
4
5
6#!/bin/bash/
str='i love you'
echo ${str:1} # 从第1个截取到末尾。注意从0开始。
echo ${str:2:2} # 从第2个截取2个。
echo ${str:0} # 全部截取。
echo ${str:-3} # 负数无效,视为0。
查找字符串
1 | #!/bin/bash/ |
expr 更多用法
STRING : REGEXP anchored pattern match of REGEXP in STRING
match STRING REGEXP same as STRING : REGEXP
substr STRING POS LENGTH #从STRING中POS位置开始截取LENGTH个字符。POS索引是从1开始的。
index STRING CHARS #在STRING中查找字符CHARS首次出现的位置,没有找到返回0
length STRING #字符串长度
数组
bash支持一维数组(不支持多维数组),并且没有限定数组的大小。类似与C语言,数组元素的下标由0开始编号。获取数组中的元素要利用下标,下标可以是整数或算术表达式,其值应大于或等于0。在Shell中,用括号来表示数组,数组元素用空格符号分割开。定义数组的一般形式为:1
2
3
4
5
6
7
8
9
10
11
12
13
array_name=(value1 value2 value3)
或者
array_name[0]=value0
array_name[1]=value1
array_name[2]=value2
echo ${array_name[2]} #读取下标为2的元素
echo ${array_name[*]} #读取所有元素
echo ${array_name[@]} #读取所有元素
echo ${#array_name[*]} #获取数组长度
echo ${#array_name[@]} #获取数组长度
echo ${#array_name[1]} #获取数组中单个元素的长度
对比数组和字符串
1 | # 字符串 |
1.4 条件控制
if 语句
语法1
2
3
4if [ expression ]
then
Statement(s) to be executed if expression is true
fi
其他两种if1
2if...elif...else...fi
if...else...fi
test命令1
2
3
4
5
6
7
8
9#!/bin/bash/
a=10
b=20
if test $a == $b
then
echo "a is equal to b"
else
echo "a is not equal to b"
fi
分支控制:case语句
case…esac与switch…case相同1
2
3
4
5
6
7grade="B"
case $grade in
"A") echo "very good";;
"B") echo "Good!";;
*)
echo "sorry";;
esac
注意:取值后面必须有 in,每个模式以 ) 结束。取值可以为变量或常数。;;等同于break;
*)等同于default:
for循环
1 | for 变量 in 列表 |
1 |
|
while循环
1 | while command |
1 |
|
until循环
1 | c=0 |
跳出循环
1 | #!/bin/bash |
continue
与break语法一样,和c的continue功能一样
1.5 函数
函数定义
1 | function function_name () { |
1 | #!/bin/bash |
Shell 函数返回值只能是整数,一般用来表示函数执行成功与否,0表示成功,其他值表示失败。如果 return 其他数据,比如一个字符串,往往会得到错误提示:numeric argument required。
函数参数
在Shell中,调用函数时可以向其传递参数。在函数体内部,通过 $n 的形式来获取参数的值,例如,$1表示第一个参数,$2表示第二个参数…这就是前面讲的特殊变量。1
2
3
4
5
6
7
8
9
10
11
12
13#!/bin/bash
function sum(){
case $# in
0) echo "no param";;
1) echo $1;;
2) echo `expr $1 + $2`;;
3) echo `expr $1 + $2 + $3`;;
*) echo "$# params! It's too much!";;
esac
}
sum 1 3 5 6
注意,
$10
不能获取第十个参数,获取第十个参数需要${10}
。当n>=10时,需要使用${n}来获取参数。
如何获取函数返回值
1 | #!/bin/bash |
1.6 其他
输出重定向
1 | command > file # 从头写 |
输入重定向
1 | commad < file |
重定向深入讲解
一般情况下,每个 Unix/Linux 命令运行时都会打开三个文件:
- 标准输入文件(stdin):stdin的fd =0 ,unix程序默认从stdin读数据
- 标准输出文件(stdout):stdout的fd=1,unix程序默认向stdout输出数据
- 标准错误文件(stderr):stderr的fd=2,unix向stderr写入错误信息
全部可用的重定向命令列表:1
2
3
4
5
6
7
8
9
10命令 说明
command > file #将输出重定向到 file。
command < file #将输入重定向到 file。
command >> file #将输出以追加的方式重定向到 file。
n > file #将文件描述符为 n 的文件重定向到 file。
n >> file
#将文件描述符为 n 的文件以追加的方式重定向到 file。
n >& m #将输出文件 m 和 n 合并。
n <& m #将输入文件 m 和 n 合并。
<< tag #将开始标记 tag 和结束标记 tag 之间的内容作为输入。
Here Document
1 | command << delimiter |
/dev/null 文件
1 | command > /dev/null |
/dev/null
是一个特殊的文件,写入到它的内容都会被丢弃;如果尝试从该文件读取内容,那么什么也读不到。但是 /dev/null
文件非常有用,将命令的输出重定向到它,会起到禁止输出的效果
Shell文件包含
1 | . filename # 或者 |
获取当前正在执行脚本的绝对路径
1 | basepath=$(pwd) |
1 | str=/www/html/php/myapp/ |