Linux–shell学习笔记(下)
判断语句
if…then 形式
类似于**C/C++
中的if-else
**语句
单层 if
命令格式:
if condition
then
语句1
语句2
...
fi
示例:
a=3
b=4
if [ "$a" -lt "$b" ] && [ "$a" -gt 2 ]
then
echo ${a}在范围内
fi
# 输出结果:
# 3在范围内
单层 if-else
命令格式:
if condition
then
语句1
语句2
...
else
语句1
语句2
...
fi
示例:
a=3
b=4
if ! [ "$a" -lt "$b" ]
then
echo ${a}不小于${b}
else
echo ${a}小于${b}
fi
# 输出结果:
# 3小于4
多层 if-elif-elif-else
命令格式:
if condition
then
语句1
语句2
...
elif condition
then
语句1
语句2
...
elif condition
then
语句1
语句2
else
语句1
语句2
...
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
...
;; # 类似于C/C++中的break
值2)
语句1
语句2
...
;;
*) # 类似于C/C++中的default
语句1
语句2
...
;;
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
语句2
...
done
示例1,输出a 2 cc,每个元素一行:
for i in a 2 cc
do
echo $i
done
示例2,输出当前路径下的所有文件名,每个文件名一行:
for file in `ls`
do
echo $file
done
示例3,输出1-10:
for i in $(seq 1 10)
do
echo $i
done
示例4,使用**{1..10}
或者****{a..z}
****:**
for i in {a..z}
do
echo $i
done
for((…;…;…)) do…done
命令格式:
for ((expression; condition; expression))
do
语句1
语句2
done
示例,输出1-10,每个数占一行:
for ((i=1; i<=10; i++))
do
echo $i
done
while…do…done
命令格式:
while condition
do
语句1
语句2
...
done
示例,文件结束符为**Ctrl + d
,输入文件结束符后read
指令返回false
。**
while read name
do
echo $name
done
until…do…done
当条件为真时结束。
命令格式:
until condition
do
语句1
语句2
...
done
示例,当用户输入**yes
**或者YES时结束,否则一直等待读入。
until [ "${word}" == "yes" ] || [ "${word}" == "YES" ]
do
read -p "Please input yes/YES to stop this program: " word
done
break 命令
跳出当前一层循环,注意与**C/C++
不同的是:break
不能跳出case
**语句。
示例:
while read name
do
for ((i=1; i<=10; i++))
do
case $i in
8)
break
;;
*)
echo $i
;;
esac
done
done
该示例每读入非**EOF
**的字符串,会输出一遍1-7。
该程序可以输入**Ctrl + d
文件结束符来结束,也可以直接用Ctrl + c
**杀掉该进程。
continue 命令
跳出当前循环。
示例:
for ((i=1; i<=10; i++))
do
if [ `expr $i % 2` -eq 0 ]
then
continue
fi
echo $i
done
该程序输出1-10中的所有奇数。
死循环的处理方式
输入**Ctrl + c
**即可。
可以直接关闭进程:
ㅤㅤ●ㅤ使用top
命令找到进程的PID
ㅤㅤ●ㅤ**输入kill -9 PID
**即可关掉此进程
函数
**bash
中的函数类似于C/C++
中的函数,但return
的返回值与C/C++
不同,返回的是exit code
,取值为0-255
,0
**表示正常结束。
如果想获取函数的输出结果,可以通过**echo
输出到stdout
中,然后通过$(function_name)
来获取stdout
**中的结果。
函数的**return
值可以通过$?
**来获取。
命令格式:
[function] func_name() { # function关键字可以省略
语句1
语句2
...
}
不获取return
值和stdout
值
示例:
func()
{
name=xhl
echo "Hello $name"
}
func
# 输出结果:
# xhl
获取return
值和stdout
值
不写**return
时,默认return 0
。**
示例:
func()
{
name=xhl
echo "Hello $name"
return 123
}
output=$(func)
ret=$?
echo "output = $output"
echo "return = $ret"
# 输出结果:
# output = Hello xhl
# return = 123
函数的输入参数
在函数内, **$1
表示第一个输入参数,$2
**表示第二个输入参数,依此类推。
注意:函数内的**$0
**仍然是文件名,而不是函数名。
示例:
func() # 递归计算 $1 + ($1 - 1) + ($1 - 2) + ... + 0
{
word=""
while [ "${word}" != 'y' ] && [ "${word}" != 'n' ]
do
read -p "要进入func($1)函数吗?请输入y/n:" word
done
if [ "$word" == 'n' ]
then
echo 0
return 0
fi if [ $1 -le 0 ]
then
echo 0
return 0
fi sum=$(func $(expr $1 - 1))
echo $(expr $sum + $1)
}
echo $(func 10)
# 输出结果:
# 55
函数内的局部变量
可以在函数内定义局部变量,作用范围仅在当前函数内。
可以在递归函数中定义局部变量。
命令格式:
local 变量名=变量值
例如:
#! /bin/bash
func() {
local name=xhl
echo $name
}
func
echo $name
# 输出结果:
# xhl
# 第一行为函数内的name变量,第二行为函数外调用name变量,会发现此时该变量不存在。
exit 命令
**exit
命令用来退出当前shell
进程,并返回一个退出状态;使用$?
**可以接收这个退出状态。
exit
命令可以接受一个整数值作为参数,代表退出状态。如果不指定,默认状态值是0
。
**exit
退出状态只能是一个介于0~255
之间的整数,其中只有0
**表示成功,其它值都表示失败。
示例:
创建脚本**test.sh
,内容如下:**
#! /bin/bash
if [ $# -ne 1 ] # 如果传入参数个数等于1,则正常退出;否则非正常退出。
then
echo "arguments not valid"
exit 1
else
echo "arguments valid"
exit 0
fi
bash test.sh
arguments valid
echo $? # 传入一个参数,则正常退出,exit code为0
0
bash test.sh
arguments not valid
echo $? # 传入参数个数不是1,则非正常退出,exit code为1
1
文件重定向
每个进程默认打开3个文件描述符:
ㅤㅤ●ㅤ**stdin
标准输入,从命令行读取数据,文件描述符为0
**
ㅤㅤ●ㅤ**stdout
标准输出,向命令行输出数据,文件描述符为1
**
ㅤㅤ●ㅤ**stderr
标准错误输出,向命令行输出数据,文件描述符为2
**
可以用文件重定向将这三个文件重定向到其他文件中。
重定向命令列表
输入和输出重定向
echo -e "Hello \c" > output.txt # 将stdout重定向到output.txt中
echo "World" >> output.txt # 将字符串追加到output.txt中
read str < output.txt # 从output.txt中读取字符串
echo $str # 输出结果:Hello World
同时重定向stdin
和stdout
创建**bash
**脚本:
#! /bin/bash
read a
read b
echo $(expr "$a" + "$b")
# 创建input.txt,里面的内容为:
3
4
# 执行命令:
bash test.sh < input.txt > output.txt # 从input.txt中读取内容,将输出写入output.txt中
cat output.txt # 查看output.txt中的内容
7
引入外部脚本
类似于**C/C++
中的include
操作,bash
**也可以引入其他文件中的代码。
语法格式:
. filename # 注意点和文件名之间有一个空格
或
source filename
示例:
创建**test1.sh
,内容为:**
#! /bin/bash
name=xhl # 定义变量name
然后创建**test2.sh
,内容为:**
#! /bin/bash
source test1.sh # 或 . [test1.sh](http://test1.sh)
echo My name is: $name # 可以使用test1.sh中的变量
执行命令:
bash test2.sh
My name is: xhl