文章目录
1、Sha-Bang
Sha-Bang是脚本开头的两个字符“#!”,脚本被读取时根据这个特定的字符串识别出这是一个需要运行解析器的脚本,而具体使用哪个解析器就是根据后面的字符串来决定,通常脚本都是使用#!/bin/bash或#!/bin/sh来解析。但现在即使不指定,系统也能识别出并且正常运行脚本,不过还是推荐显式地指定,因为即使机器能识别,我们也还是可以根据这个标识一眼就能识别出这是一个shell脚本。
2、“变量”
2.1 变量
定义规则:
- 只能英文字母、数字和下划线,且首字母不能是数字;
- 不能使用空格、标点符号和shell的关键字;
有效的变量定义示例:
var
_var
var1
错误的示例:
va%r
2var
使用变量:
-
变量赋值时“=”两边不能有空格,并且可以多次赋值;
-
变量赋值时全部以字符串形式解析,即便是单个数字;
-
使用时加上美元符“$”取值。
var="hello"
echo $var # 有效,输出hello
echo ${var} # 有效,输出hello,推荐使用“{}”可以划定变量名称范围
echo $"var" # 无效,输出var
echo $'var' # 无效,输出var
echo $`var` # 无效,没有var这个命令,且$符号为多余
echo $(var) # 无效,没有var这个命令
name="Mike"
echo "Hello, $name !" # 双引号会解析变量:Hello, Mike !
echo 'Hello, $name !' # 单引号原样输出:Hello, $name !
设置变量只读:
ro_var="Mike"
readonly ro_var
ro_var="Amy" # 无法再次修改并提示
local(本地)变量:
#!/bin/bash
str="hello"
function func(){
local str="world"
echo "str: $str"
}
echo "str: $str" # hello
func # world
echo "str: $str" # hello
删除变量:
输出的变量不能再次使用,并且不能删除readonly变量。
unset var
2.2 运算
进制:
格式:进制#数字
echo $((3#101)) # 输出:10
echo $[5#100] # 输出:25
运算:
a=1; b=3; c=5
echo $((a*b+c)) # 输出:8
echo $[a*b+c] # 输出:8
注: $(()) 和 $[] 效果一样,但都不能单独使用,必须立马使用它的运算结果,否则认为是命令导致报错。另外,运算中的a/b/c可以直接使用,也可以加上“$”符号。
2.3 字符串
获取字符串长度:
string="hello, world!"
echo ${#string} # 输出:13
提取子字符串:
string="hello, world!"
echo ${string:0:5} # 输出:hello
2.4 数组
array1=(Mike Green Amy)
array2=(
Mike
Green
Amy
)
array3[0]="Mike"
array3[10]="Amy" # 下标范围没有限制
echo ${array1[0]} # 输出元素:Mike
echo ${array2[2]} # 输出元素:Amy
echo ${#array3[0]} # 输出单个元素长度:4
echo ${array1[@]} # 输出数组所有元素:Mike Green Amy
echo ${array1[*]} # 输出数组所有元素:Mike Green Amy
3、流程控制
3.1 if 判断
情景1:单个if语句
if condition
then
# cmd...
fi
或
if condition; then
# cmd...
fi
情景2:if else-if else
if condition1; then
# cmd...
elif condition2; then
# cmd...
else
# cmd...
fi
注:“condition”判断可以参考下一章的test命令使用。
3.2 case 分支
case "$var" in
"$val1") # 有无双引号皆可
# cmd...
;;
val2 | val3) # 可以同时匹配多个
# cmd...
;;
*)
# cmd...
;;
esac
3.3 for 循环
for var in item1 item2 ...
do
# cmd...
done
或
for var in item1 item2; do
# cmd...
done
3.4 while 循环
while condition
do
# cmd...
done
或
while condition; do
# cmd...
done
3.5 until 循环
一直执行一系列命令直到条件为true时推出,与while循环的处理方式刚好相反,一般情况while会优于until循环。
until condition
do
# cmd...
done
或
until condition; do
# cmd...
done
3.6 跳出循环
与C语言类似,也提供了以下2个跳出循环的关键字,并且作用一样:
- continue:跳出本次循环,继续判断是否再次进入下一轮的循环
- break:跳出整个循环。
4、test命令
test命令(别名“[”)可以用于shell中文件、数值、字符串三方面的条件测试,一般还提供内建结构“[ ]”,新版本bash还提供了“[[ ]]”,使用时需要注意测试表达式与test命令之间应有空格。
4.1 文件判断
| 条件 | 判断说明 |
|---|---|
| -e/-a | 文件是否存在 |
| -d | 是否为目录 |
| -f | 是否为普通文件 |
| -b | 是否为块设备文件 |
| -c | 是否为字符设备 |
| -p | 是否为管道 |
| -S | 是否为Socket |
| -h/-L | 是否为符号链接 |
| -r | 文件是否可读 |
| -w | 文件是否可写 |
| -x | 文件是否可写 |
示例:
#!/bin/bash
# test命令写法1:
if test -e ~/.vimrc; then
echo "~/.vimrc is exist!"
fi
# test命令写法2:
if [ -e ~/.vimrc ]; then
echo "~/.vimrc is exist!"
fi
# 条件否(!)
if [ ! -c /dev/console ];then
mknod /dev/console c 5 1
fi
if [ ! -c /dev/null ];then
mknod /dev/null c 1 3
fi
4.2 数值比较
| 条件 | 说明 |
|---|---|
| -eq | 是否相等 |
| -ne | 是否不等 |
| -gt 或 > | 是否大于 |
| -ge 或 >= | 是否大于等于 |
| -lt 或 < | 是否小于 |
| -le 或 <= | 是否小于等于 |
注:表格上“-gt 或 >”功能虽然相同,但使用方法不完全等效,详情见示例。
示例:
#!/bin/bash
num1=12
num2=34
if [ "$num1" -lt "$num2" ];then
echo "num1 < num2"
fi
if(("$num1" < "$num2")); then
echo "num1 < num2"
fi
4.3 字符串测试
| 条件 | 说明 |
|---|---|
| =/== | 是否等于 |
| != | 是否不等 |
| > | 根据ASCII顺序判断,在[]需要加上转义字符“\” |
| < | 根据ASCII顺序判断,在[]需要加上转义字符“\” |
| -z | 长度是否为0 |
| -n | 长度是否不为0 |
示例:
#!/bin/bash
str1="hello"
str2="Hello"
if [ $str1 = $str2 ]; then
echo "str1 == str2"
else
echo "str1 != str2"
fi
5、函数
5.1 定义与使用
形式1:使用function关键字定义
function func_name(){
# cmd...
}
形式2:与C语言类似
func_name(){
# cmd...
}
注:bash不像C语言一样可以声明函数,所以应该在调用函数之前先定义好,在调用函数时直接使用函数名即可,如:
#!/bin/bash
func(){
echo "I'm in func!"
}
echo "before call func!"
func
echo "after call func!"
5.2 函数参数
| 参数 | 说明 |
|---|---|
| $0、$1… | 命令行参数,类比于C语言的argv[0]、argv[1]… |
| $# | 命令行参数个数,类比于C语言的argc |
| $* | 命令行所有参数作为一个整体,引用时需加双引号"" |
| $@ | 命令行所有参数,但每个都是一个独立的字符串,引用时也需加双引号"" |
5.3 函数/程序返回值
| 符号 | 说明 |
|---|---|
| $? | 获取上次函数/程序退出的状态;成功返回0,失败返回1。 (只能查看一次,因为使用echo等命令后又会被替换为该命令的返回值) |
6、文件
6.1 包含文件
包含其他文件可以让编写脚本时减少编写重复的代码,方便开发。命令格式如下:
. otherfile
source otherfile
示例:
ip.conf
ip="192.168.1.1"
test.sh
#!/bin/bash
source ./ip.conf
echo "IP address: ${ip}"
注:被包含的文件可以不具备可执行权限。
6.2 其他命令
| 命令 | 说明 | 示例 |
|---|---|---|
| realpath | 查看文件的绝对路径,多用于查看软链接文件的真实文件 | realpath file.txt |
| dirname | 去除文件名中的非目录部分,多用于查看文件所在路径 | dirname /home/book/… |
7、重定向
7.1 输出重定向
| 命令 | 说明 |
|---|---|
| cmd > file | 将cmd命令的输出写到file中 |
| cmd >> file | 将cmd命令的输出追加到file中 |
| cmd > file 2>&1 | 将cmd命令的标准错误(stderr描述符为2)也重定向到标准输出并重定向到文件file中 |
| cmd > /dev/null | 将cmd命令的输出丢弃(/dev/null类似于一个黑洞) |
7.2 输入重定向
| 命令 | 说明 |
|---|---|
| cmd < file | 原本由键盘输入的更改为file文件输入 |
8、管道
|是管道的符号,它将前一个命令的输出作为下一个命令的输入。一般左右两边是不同的2个进程,部分命令需要前面加上xargs将管道或标准输入数据转换成命令行参数。例如:
dmesg | grep "USB"
find ./ -name *.conf | xargs ls -l
本文详细介绍了Shell脚本中的变量定义与使用、运算、流程控制(if、case、循环、测试命令)、函数、文件操作、重定向和管道技巧。通过实例演示了如何进行变量赋值、比较、字符串处理和流程控制的实战应用。
29万+

被折叠的 条评论
为什么被折叠?



