shell
简介
Shell是一种脚本语言,通常用于在Unix和类Unix操作系统上进行命令行交互。它是用户与操作系统内核之间的接口,允许用户通过命令行或脚本文件来控制计算机上的操作。Shell程序通常用于执行复杂的任务,例如文件操作、网络通信、进程控制等。
Shell语言具有很高的灵活性,可以根据需要编写自定义脚本来自动化任务。Shell脚本通常包含一系列命令和流程控制语句,可以执行文件操作、程序运行、环境变量设置等任务。在Unix和类Unix操作系统中,常见的Shell包括Bash、Csh、Ksh等,它们都具有各自的特点和用法。Linux中默认使用bash。
运行
- 文件开头需写
#! /bin/bash
,指明默认的脚本解释器。 - 运行方式:
- 用解释器执行(可以没有权限):
bash test.sh
,test.sh是Shell脚本文件的名称。 - 作为可执行文件执行(必须要有权限):
chmod +x test.sh
,使脚本具有可执行权限。然后./test.sh
直接运行。 - 在终端中执行Shell命令,并执行脚本:
echo "echo Hello, World!" | sh
其中第一种方法较常用。
语法
注释
-
单行注释(#
注释)
在Shell脚本中,一行代码以 #
开头时,该行代码就被认为是注释,Shell 解释器会将这一行代码忽略。例如:
#! /bin/bash
echo "Hello World!"
-
多行注释
在Shell脚本中,我们也可以使用一对 : << EOF
和 EOF
来实现多行注释,其中一对EOF可以换成其他字符串,如: << qingqiu
qingqiu
。
#! /bin/bash
: << suibian
第一行注释
第二行注释
第三行注释
suibian
echo "Hello, World!"
变量
变量的命名规则
在Shell中,变量名遵循以下命名规则:
- 变量名必须以字母或下划线开头。
- 变量名中只能包含字母、数字和下划线。
- 变量名不能以数字开头。
- 变量名区分大小写。
- 变量名和变量值之间不能有空格。
- 如果变量值包含空格,需要使用引号将变量值括起来,例如
name="qing qiu"
。
处理变量
在Shell中,变量可以用来存储字符串或数字等信息。可以通过定义变量、给变量赋值、使用变量等操作来进行变量处理。
-
定义变量
定义变量有三种方法
- name=qingqiu
- name=“qingqiu”
- name=‘qingqiu’
其中不加引号和加双引号效果相同,支持变量替换和转义字符的解析,例如:
name="qingqiu"
echo "My name is $name"
而单引号不支持变量替换和转义字符的解析,在单引号中,所有的字符都会被当作普通字符处理,例如:
name="qingqiu"
echo 'My name is $name'
-
给变量赋值
可以使用=号来给变量赋值,等号两边不能有空格,否则会报错。
-
使用变量
使用变量时需要在变量名前加上$,或者${},{}
用于识别变量边界。例如:
name=qingqiu
echo $name
echo ${name}
echo $nameye
echo ${name}ye
-
只读变量
readonly
或者declare
可以将变量变为只读,修改只读变量时会报错。
name=qingqiu
readonly name
declare -r name
name=a
取消只读属性:
unset -v name
-
删除变量
unset
可以删除变量。
name=qingqiu
unset name
echo $name
要想删除只读变量,需要先取消只读属性,再用unset
删除。
变量类型
局部变量与全局变量
- 自定义变量(局部变量)
子进程不能访问的变量。 - 环境变量(全局变量)
子进程可以访问的变量。
自定义变量与环境变量可以互相转换:
自定义变量→环境变量
name=qingqiu
export name
declare -x name
环境变量→自定义变量
export name=qingqiu
declare +x name
字符串
在shell中,字符串可以用单引号、双引号或不用引号来表示。单引号与双引号有区别,参考上述定义变量处。
字符串的操作
数字
数字变量用来存储数字类型的数据。在shell中,数字变量可以是整数或浮点数。
数组
数组中可以存放多个不同类型的值,下标从0开始,初始化时不需要指明数组大小。
- 定义
-
使用圆括号括起数组元素,并用空格隔开。例如:
array=(666 qing "qiu" haha)
-
使用花括号括起数组元素,并用逗号隔开。例如
array={666, qing, "qiu", haha}
-
直接定义数组中的某个元素的值:
array[0]=666
array[1]=qing
array[2]="qiu"
array[3]=haha
直接定义某个元素的值时,下标可以不连续。例如:
array[0]=666
array[6]=qing
array[9]=“qiu”
array[999]=haha
echo ${#array[@]}
-
读取某个元素的值
${array[index]}
echo ${array[0]}
echo ${array[1]}
echo ${array[2]}
echo ${array[3]}
-
读取整个数组
${array[@]}
${array[*]}
echo ${array[@]}
echo ${array[*]}
在读取整个数组时,未定义的部分不会显示。例如:
array[0]=666
array[6]=qing
array[9]=qiu
array[999]=haha
echo ${array[@]}
-
数组长度
${#array[@]}
${#array[*]}
echo ${#array[@]}
echo ${#array[*]}
默认变量
默认变量是指在Shell中已经定义好的一些特殊变量,可以在Shell脚本中直接使用。一些常用的默认变量如下:
$0
: 当前脚本的文件名。$1
~ $9
: 传递给脚本或函数的参数。其中,$1
表示第一个参数,$2
表示第二个参数,以此类推。如果>9,需要用{}括起来,例如:
${10}
。$#
: 传递给脚本或函数的参数个数。$*
: 以一个单字符串显示所有向脚本传递的参数。参数之间用空格分隔。$@
: 与$*
类似,但是每个参数都是独立的字符串,可以避免参数中含有空格等特殊字符的问题。$?
: 上一个命令或者函数的退出状态,0表示成功,非0表示失败。$$
: 当前Shell进程的进程号。$(command)
:返回command
这条命令的标准输出(可嵌套)。command
:返回command
这条命令的标准输出(不可嵌套)。
expr命令
expr 表达式
用于求表达式的值。
说明
- 用空格隔开每一项。
- 使用shell特定的字符需转义,或用反引号``(fn+~)括起来。
- 对包含空格和其他特殊字符的字符串要用引号括起来。
expr
会在stdout中输出结果。如果为逻辑关系表达式,则结果为真时,stdout输出1,否则输出0。真为1,假为0expr
的exit code
:如果为逻辑关系表达式,则结果为真时,exit code
为0,否则为1。真为0,假为1
字符串表达式
-
length string
返回string
的长度
-
index string charset
charset
中任意单个字符在string
中最前面的字符位置,下标从1开始。如果string
中完全不存在charset
中的字符,则返回0。
-
substr string position length
返回string
字符串中从第position
个位置开始,长度最大为length
的子串。如果position
或length
为0、负数、或非数值,则返回空字符串。
str="Hello World!"
echo `expr length "$str"`
echo `expr index "$str" ala`
echo `expr substr "$str" 2 3`
整数表达式
expr
支持普通算数操作,算术表达式优先级低于字符串表达式,高于逻辑关系表达式。
+ -
加减运算。两端参数回转换成整数,如果转换失败则报错。* / %
乘、除、取模运算,*
需要转义。两端参数会转换为整数,如果转换失败则报错。()
可以改变优先级,但使用时需要转义。
a=5
b=6
echo `expr $a + $b`
echo `expr $a / $b`
echo `expr \( $a + 1 \) \* \( $b + 4 \)`
逻辑表达式
-
|
如果第一个参数非空且非0,则返回第一个参数的值,否则返回第二个参数的值,但要求第二个参数的值也是非空或非0,否则返回0。如果第一个参数是非空或非0时,不会计算第二个参数。
-
&
如果两个参数都非空且非0,则返回第一个参数,否则返回0。如果第一个参为0或为空,则不会计算第二个参数。
-
< <= = == != >= >
比较两端的参数,如果为true,则返回1,否则返回0。==与=是同义词。expr首先尝试将两端参数转换为整数,并做算术比较,如果转换失败,则按字符集排序规则做字符比较。
-
()
可以改变优先级,但需要转义。
read命令
read命令用于从标准输入中读取单行数据。当读到文件结束符时,exit code为1,否则为0。
参数说明
- -p:后面可以接提示信息。
- -t:后面跟秒数,定义输入字符的等待时间,超过等待时间后会自动忽略此命令。
read name
echo $name
read -p "Please input: " -t 30 name
echo命令
echo
用于输出字符串。
-
显示普通字符串
echo "qingqiu"
echo qingiu
-
显示转义字符
echo "\"qingqiu\""
echo \"qingqiu\"
-
原样输出字符
name=qingqiu
echo '$name\"'
-
显示变量
name=qingqiu
echo "I'm $name"
-
显示换行
echo -e "hello\n"
-
显示不换行
echo -e “hello\c”
-
显示结果定向至文件
echo "qingqiu" > output.txt
-
显示命令执行结果
echo `date`
printf命令
用于格式化输出,类似于C/C++
中的printf
函数。
test命令与判断符号[]
逻辑运算符
&&
表示与,||
表示或。exit code
为0时表示真;非零时表示假。(与C/C++
定义相反)。
test命令
test
命令用于判断文件类型以及比较变量,用exit code
返回结果,为真,非0为假。
-
判断文件类型
test -e filename
test -f filename
test -d filename
-
判断文件权限
test -r
test -w
test -x
test -s
-
比较整数
test $a -eq $b
test $a -ne $b
test $a -gt $b
test $a -lt $b
test $a -ge $b
test $a -le $b
-
比较字符串
test -z string
test -n string
test str1 == str2
test str1 != str2
-
多重条件判定
test -r filename -a -x filename
test -r filename -o -x filename
test ! -x file
判断符号[]
[]
与test
用法几乎一模一样,更常用于if
语句中。另外[[]]
是[]
的加强版,支持的特性更多。
注意:
[]
是一个命令,里面的每一项都要用空格隔开- 中括号内的变量,最好用双引号括起来
- 中括号内的常数,最好用单或双引号括起来
判断语句
if…then
类似于C/C++
中的if-else
语句。
-
单层if
if condition
then
语句1
...
fi
a=3
b=4
if [ "$a" -lt "$b" ] && [ "$a" -gt 2 ]
then
echo ${a}在范围内
fi
-
单层if-else
if condition
then
语句1
...
else
语句1
...
fi
a=3
b=4
if [ "$a" -lt "$b" ]
then
echo ${a}小于${b}
else
echo ${a}不小于${b}
fi
-
多层if-elif-elif-else
if condition
then
语句1
...
elif condition
then
语句1
...
elif condition
then
语句1
else
语句1
...
fi
a=4
if [ $a -eq 1 ]
then
echo ${a}等于1
elif [ $a -eq 2 ]
then
echo ${a}等于2
elif [ $a -eq 3 ]
then
echo ${a}等于3
else
echo 其他
fi
case…esac
类似于C/C++
中的switch
语句。
case $变量名 in
值1)
语句1
...
;;
值2)
语句1
...
;;
*)
语句1
...
;;
esac
a=4
case $a in
1)
echo ${a}等于1
;;
2)
echo ${a}等于2
;;
3)
echo ${a}等于3
;;
*)
echo 其他
;;
esac
循环语句
for…in…do…done
for var in val1 val2 val3
do
语句1
...
done
for i in q i n g
do
echo $i
done
for file in `ls`
do
echo $file
done
for i in $(seq 1 10)
do
echo $i
done
for i in {a..z}
do
echo $i
done
for ((…;…;…)) do…done
类似于C/C++
中的for
循环。
for ((初值; 条件; 操作))
do
语句1
...
done
for((i=1; i<=10; i++))
do
echo $i
done
while…do…done
while condition
do
语句1
...
done
while read name
do
echo $name
done
until…do…done
条件为真时结束。
until condition
do
语句1
...
done
until [ "${word}" == "yes" ] || [ "$word" == "YES" ]
do
read -p "Please input yes/YES to stop:" word
done
跳出循环
-
break命令
跳出当前一层循环,break
不能跳出case
语句。
while read name
do
for ((i=1;i<=10;i++))
do
case $i in
8)
break
;;
*)
echo $i
;;
esac
done
done
-
continue命令
跳出当前循环。
for ((i=1;i<=10;i++))
do
if [ `expr $i % 2` -eq 0 ]
then
continue
fi
echo $i
done
死循环处理
- 使用
top
命令找到该进程ID。 - 输入
kill -9 PID
关掉此进程。
函数
bash
中的函数类似于C/C++
中的函数,但return
的返回值与C/C++
不同,返回的是exit code
,取值为0-255,0表示正常结束。
如果想获取函数的输出结果,可以通过echo
输出到stdout
中,然后通过$(function_name)
来获取stdout
中的结果。
函数的return
值可以通过$?
来获取。
exit命令
-
exit
命令用来退出当前shell进程,并返回一个退出状态;使用$?可以接收这个退出状态。
-
exit
命令可以接受一个整数值作为参数,代表退出状态。如果不指定,默认状态值是 0。
-
exit
退出状态只能是一个介于 0~255 之间的整数,其中只有 0 表示成功,其它值都表示失败。
文件重定向
每个进程默认打开3个文件描述符:
- stdin标准输入,从命令行读取数据,文件描述符为0
- stdout标准输出,向命令行输出数据,文件描述符为1
- stderr标准错误输出,向命令行输出数据,文件描述符为2
可以用文件重定向将这三个文件描述符重定向到其他文件中。
命令 | 说明 |
---|
command > file | 将stdout重定向到file中 |
command < file | 将stdin重定向到file中 |
command >> file | 将stdout以追加方式重定向到file中 |
command n> file | 将文件描述符n重定向到file中 |
command n>> file | 将文件描述符n以追加方式重定向到file中 |
引入外部脚本
类似于C/C++
中的include
操作,bash
也可以引入其他文件中的代码。
语法格式:
. filename
source filename
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)