这里Shell脚本特指Linux系统中命令行中的脚本语言.
近来发现在纯软件开发过程中还是有必要深入学习Shell脚本,以便在Linux下开发更加方便.

Shell Overview

Shell是一种脚本语言,不用编译,只需shell解释器解释执行.
常见的 Shell 有 sh、bash、csh、tcsh、ash 等。
bash 由 GNU 组织开发,保持了对 sh shell 的兼容性,是各种 Linux 发行版默认配置的 shell。
查看可用的shell解释程序:

cat /etc/shells

查看当前默认的Shell:

echo $SHELL

一般Shell提示符分为两种:
bash shell 默认的提示符是美元符号 $ ;对于超级用户(root 用户),Bash Shell 默认的提示符是井号 #.

第一个shell脚本文件:
test.sh

#!/bin/bash
echo "Hello World"

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

执行shell脚本:

chmod +x test.sh
# 方式一
./test.sh
# 方式二
/bin/bash test.sh

Shell 变量

Shell中,每一个变量的值都是字符串.

定义变量

var1=1
var2='1'
var3="1"

变量名=变量值
注意点:

  • 赋值号的周围不能有空格
  • 变量值中没有空白符,则可以不加单双引号
  • 变量名由数字、字母、下划线组成;必须以字母或者下划线开头; 不能使用 Shell 里的关键字

使用变量

v_program="Java"
echo $v_name
echo ${v_name}
echo "I like $v_name"
echo "I like ${v_name}Script"

使用一个定义过的变量,只要在变量名前面加美元符号$即可
变量名外面的花括号{ }是可选的,加花括号是为了帮助解释器识别变量的边界

单引号和双引号的区别

#!/bin/bash
url="https://openthinks.com"
website1='${url}'
website2="${url}"
echo $website1
echo $website2

输出结果:
${url}
https://openthinks.com

以单引号' '包围变量的值时,单引号里面是什么就输出什么
以双引号" "包围变量的值时,输出时会先解析里面的变量和命令

将命令的结果赋值给变量

v_dir1=`ls -l`
v_dir2=$(ls -al)

第一种方式把命令用反引号包围起来
第二种方式把命令用$()包围起来

只读变量

使用 readonly 命令可以将变量定义为只读变量

#!/bin/bash
url="https://openthinks.com"
readonly url
url="other"

输出结果:
line 4: url: readonly variable

删除变量

unset v_name

注意: 变量被删除后不能再次使用;unset 命令不能删除只读变量。

Shell 特殊变量

变量含义
$0当前脚本的文件名
$n传递给脚本或函数的参数。n 是一个数字,表示第几个参数。例如,第一个参数是$1,第二个参数是$2。
$#传递给脚本或函数的参数个数。
$*传递给脚本或函数的所有参数。
$@传递给脚本或函数的所有参数。
$?上个命令的退出状态,或函数的返回值。
$$当前Shell进程ID。对于 Shell 脚本,就是这些脚本所在的进程ID。

命令行参数

运行脚本时传递给脚本的参数称为命令行参数。
命令行参数用 $n 表示,例如,$1 表示第一个参数,$2 表示第二个参数,依次类推。

$* 和 $@ 的区别

$*$@ 都表示传递给函数或脚本的所有参数,不被双引号(" ")包含时,都以"$1" "$2" … "$n" 的形式输出所有参数。

但是当它们被双引号(" ")包含时,"$*" 会将所有的参数作为一个整体,以"$1 $2 … $n"的形式输出所有参数;"$@" 会将各个参数分开,以"$1" "$2" … "$n" 的形式输出所有参数。

注意: 此处被双引号包围时指 $*$@ 这两个特殊变量, 而不是指shell脚本参数
test.sh

#!/bin/bash
echo "\$*=" $*
echo "\"\$*\"=" "$*"
echo "\$@=" $@
echo "\"\$@\"=" "$@"
echo "print each param from \$*"
for var in $*
do
    echo "$var"
done
echo "print each param from \$@"
for var in $@
do
    echo "$var"
done
echo "print each param from \"\$*\""
for var in "$*"
do
    echo "$var"
done
echo "print each param from \"\$@\""
for var in "$@"
do
    echo "$var"
done

执行

./test.sh a b c d e
$*= a b c d e
"$*"= a b c d e
$@= a b c d e
"$@"= a b c d e
print each param from $*
a
b
c
d
e
print each param from $@
a
b
c
d
e
print each param from "$*"
a b c d e
print each param from "$@"
a
b
c
d
e

Shell 替换

特殊符号替换

表达式中包含特殊字符,Shell 将会进行替换

  • 在双引号中使用变量就是一种替换
  • 转义字符替换
echo "hello world\n"

echo -e "hello world\n"

结果:

hello world\n
hello world

-e 开启转义 -E 禁止转义 -n 禁止插入换行符

转义字符含义
\反斜杠
a警报,响铃
b退格(删除键)
f换页(FF),将当前位置移到下页开头
n换行
r回车
t水平制表符(tab键)
v垂直制表符

命令替换

命令替换的语法:

# 反引号
`command`
USERS=`who | wc -l`
echo "Logged in user count is $USERS"

结果:

Logged in user count is 1

wc 功能为统计指定文件中的字节数、字数、行数, 并将统计结果显示输出

- c 统计字节数
- l 统计行数
- w 统计字数

变量替换

变量替换可以根据变量的状态(是否为空、是否定义等)来改变它的值

形式说明
${var}变量本来的值
${var:-word}如果变量 var 为空或已被删除(unset),那么返回 word,但不改变 var 的值。
${var:=word}如果变量 var 为空或已被删除(unset),那么返回 word,并将 var 的值设置为 word。
${var:?message}如果变量 var 为空或已被删除(unset),那么将消息 message 送到标准错误输出,可以用来检测变量 var 是否可以被正常赋值。若此替换出现在Shell脚本中,那么脚本将停止运行。
${var:+word}如果变量 var 被定义,那么返回 word,但不改变 var 的值。

Shell 运算符

Bash 支持很多运算符,包括算数运算符、关系运算符、布尔运算符、字符串运算符和文件测试运算符

原生bash不支持简单的数学运算,但是可以通过expr命令来实现

val=`expr 4 + 4`
echo "4+4=$val"

结果:

4+4=8

注意点:

  • 表达式和运算符之间要有空格, 4 + 4 运算符 + 左右有空格
  • 完整的表达式要被 ` ` 反引号包含

算术运算符

算术运算符列表

运算符说明举例
+加法expr $a + $b
-减法expr $a - $b
*乘法expr $a \* $b
/除法expr $b / $a
%取余expr $b % $a
=赋值a=$b 将把变量 b 的值赋给 a
==相等用于比较两个数字,相同则返回 true。 [ $a == $b ]
!=不相等用于比较两个数字,不相同则返回 true。 [ $a != $b ]

注意:

  • 条件表达式要放在方括号之间,并且要有空格,例如 [$a==$b] 是错误的,必须写成 [ $a == $b ]
  • 乘号(*)前边必须加反斜杠()才能实现乘法运算

关系运算符

关系运算符只支持数字,不支持字符串,除非字符串的值是数字。

关系运算符列表

运算符说明举例
-eq检测两个数是否相等,相等返回 true。[ $a -eq $b ]
-ne检测两个数是否相等,不相等返回 true。[ $a -ne $b ]
-gt检测左边的数是否大于右边的,如果是,则返回 true。[ $a -gt $b ]
-lt检测左边的数是否小于右边的,如果是,则返回 true。[ $a -lt $b ]
-ge检测左边的数是否大等于右边的,如果是,则返回 true。[ $a -ge $b ]
-le检测左边的数是否小于等于右边的,如果是,则返回 true。[ $a -le $b ]