bash简介

bash是Linux的一种Shell,Linux的Shell种类很多,常见的有:

  • Bourne Shell(/usr/bin/sh或/bin/sh)
  • Bourne Again Shell(/bin/bash)
  • C Shell(/usr/bin/csh)
  • K Shell(/usr/bin/ksh)
  • Shell for Root(/sbin/sh)

bash也就是 Bourne Again Shell,在一般情况下,人们并不区分 Bourne Shell 和 Bourne Again Shell,所以,像 #!/bin/sh,它同样也可以改为 #!/bin/bash。

#!告诉系统气候路径所指定的程序即是解释此脚本文件的Shell程序,不可省略。

新建的shell脚本要加可执行权限,执行命令的文件名前要加./,否则系统会去PATH里找脚本文件,从而因找不到该文件而报错。

chmod +x ./test.sh  #使脚本具有执行权限
./test.sh #执行脚本

基本语法

1.变量

定义变量——不加$符号,变量名和等号之间不能有空格。

赋值两种方式:直接赋值、通过linux命令赋值

name="summer"
for file in `ls /etc`

for file in $(ls /etc)

使用变量——需要加$符号,可以加花括号括起来(推荐)

for skill in Ada Coffe Action Java; do
echo "I am good at ${skill}Script"
done

变量操作

  • 设置只读变量:变量前加 readonly
  • 删除变量:变量前加 unset

2.字符串

字符串可以用单引号、双引号也可以不用引号

单引号字符串的限制:

  • 单引号里的任何字符都会原样输出,单引号字符串中的变量是无效的;
  • 单引号字串中不能出现单独一个的单引号(对单引号使用转义符后也不行),但可成对出现,作为字符串拼接使用。

双引号的优点:

  • 双引号里可以有变量
  • 双引号里可以出现转义字符

拼接字符串

your_name="runoob"
# 使用双引号拼接
greeting="hello, "$your_name" !"
greeting_1="hello, ${your_name} !"
echo $greeting $greeting_1

# 使用单引号拼接
greeting_2='hello, '$your_name' !'
greeting_3='hello, ${your_name} !'
echo $greeting_2 $greeting_3

输出结果

hello, runoob ! hello, runoob !
hello, runoob ! hello, ${your_name} !

获取字符串长度

变量前加一个#号

string="abcd"
echo ${#string} # 输出 4

提取字符串

字符串索引从0开始,${string:1:4} 表示字符串从第2个字符开始截取4个字符

string="runoob is a great site"
echo ${string:1:4} # 输出 unoo

查找子字符串

查找字符 i 或 o 的位置(哪个字母先出现就计算哪个)

string="runoob is a great site"
echo `expr index "$string" io` # 输出 4

3.数组

支持一维数组,不支持多维数组,下标0开始编号。

定义数组:括号表示,空格分开

array_name=(value0 value1 value2 value3)

或者

array_name=(
value0
value1
value2
value3
)

还可以单独定义数组的各个分两,可以不使用下标,下标范围无限制

array_name[0]=value0
array_name[1]=value1
array_name[n]=valuen

读取数组

${数组名[下标]}

使用 @ 符号可以获取数组中的所有元素,例如:

echo ${array_name[@]}

获取数组长度:

# 取得数组元素的个数
length=${#array_name[@]}
# 或者
length=${#array_name[*]}
# 取得数组单个元素的长度
lengthn=${#array_name[n]}

关联数组(大概可以理解为python中的dict)

声明

declare -A array_name
declare -A site
site["google"]="www.google.com"
site["runoob"]="www.runoob.com"
site["taobao"]="www.taobao.com"

echo ${site["runoob"]}

‘#’和‘@’用于访问数组全部内容,数组前加!号获取键值,数组前加#号用于获取数组长度。

#!/bin/bash
declare -A site
site["google"]="www.google.com"
site["runoob"]="www.runoob.com"
site["taobao"]="www.taobao.com"

echo "数组的元素为: ${site[*]}"
echo "数组的元素为: ${site[@]}"

echo "数组的键为: ${!site[*]}"
echo "数组的键为: ${!site[@]}"

echo "数组元素个数为: ${#site[*]}"
echo "数组元素个数为: ${#site[@]}"
数组的元素为: www.google.com www.runoob.com www.taobao.com
数组的元素为: www.google.com www.runoob.com www.taobao.com
数组的键为: google runoob taobao
数组的键为: google runoob taobao
数组元素个数为: 3
数组元素个数为: 3

4.注释

单行注释用#号

多行注释:

:<<EOF
注释内容...
注释内容...
注释内容...
EOF

5.传递参数

我们可以在执行 Shell 脚本时,向脚本传递参数,脚本内获取参数的格式为:$n。n 代表一个数字,1 为执行脚本的第一个参数,2 为执行脚本的第二个参数,以此类推……

#!/bin/bash
echo "执行的文件名:$0";
echo "第一个参数为:$1";
echo "第二个参数为:$2";
echo "第三个参数为:$3";

执行上述脚本并输出,可见执行的文件名为0号参数,后面依次为参数1,2,3

$ chmod +x test.sh 
$ ./test.sh 1 2 3
执行的文件名:./test.sh
第一个参数为:1
第二个参数为:2
第三个参数为:3

6.运算符

算数运算符

bash脚本编程学习笔记_编程

关系运算符

bash脚本编程学习笔记_bash_02

布尔运算符

bash脚本编程学习笔记_bash_03

逻辑运算符

注意有两层中括号

bash脚本编程学习笔记_脚本_04

字符串运算符

bash脚本编程学习笔记_bash_05

文件测试运算符

bash脚本编程学习笔记_编程_06

7.echo命令

-e 开启转义

echo -e "OK! \n" # -e 开启转义
echo "It is a test"
OK!

It is a test

显示命令执行结果,用反引号`把命令括起来

echo `date`
Thu Jul 24 10:08:46 CST 2014

8.test命令

用于检查某个条件是否成立,可以进行数值、字符和文件三个方面的测试。

num1=100
num2=100
if test $[num1] -eq $[num2]
then
echo '两个数相等!'
else
echo '两个数不相等!'
fi

代码中的 [] 执行基本的算数运算

​9.流程控制

条件判断

if condition
then
command1
command2
...
commandN
fi

末尾的 fi 就是 if 倒过来拼写

if else 的 [...] 判断语句中大于使用 -gt,小于使用 -lt。

if [ "$a" -gt "$b" ]; then
...
fi

如果使用 ((...)) 作为判断语句,大于和小于可以直接使用 > 和 <。

if (( a > b )); then
...
fi

for循环

for var in item1 item2 ... itemN
do
command1
command2
...
commandN
done

while循环

while condition
do
command
done
#!/bin/bash
int=1
while(( $int<=5 ))
do
echo $int
let "int++"
done

until循环

until循环执行一系列命令直至条件为true时停止。

until condition
do
command
done
#!/bin/bash

a=0

until [ ! $a -lt 10 ]
do
echo $a
a=`expr $a + 1`
done
case...esac

多选择语句,每个case分支用右圆括号开始,用两个分号;;表示break。esac(case反过来)作为结束标记。

如果无一匹配模式,使用星号 * 捕获该值,再执行后面的命令。

case 值 in
模式1)
command1
command2
...
commandN
;;
模式2)
command1
command2
...
commandN
;;
esac
echo '输入 1 到 4 之间的数字:'
echo '你输入的数字为:'
read aNum
case $aNum in
1) echo '你选择了 1'
;;
2) echo '你选择了 2'
;;
3) echo '你选择了 3'
;;
4) echo '你选择了 4'
;;
*) echo '你没有输入 1 到 4 之间的数字'
;;
esac

跳出循环

break:跳出所有循环

#!/bin/bash
while :
do
echo -n "输入 1 到 5 之间的数字:"
read aNum
case $aNum in
1|2|3|4|5) echo "你输入的数字为 $aNum!"
;;
*) echo "你输入的数字不是 1 到 5 之间的! 游戏结束"
break
;;
esac
done

continue:跳出当前循环

#!/bin/bash
while :
do
echo -n "输入 1 到 5 之间的数字: "
read aNum
case $aNum in
1|2|3|4|5) echo "你输入的数字为 $aNum!"
;;
*) echo "你输入的数字不是 1 到 5 之间的!"
continue
echo "游戏结束"
;;
esac
done

10.函数

定义函数

[ function ] funname [()]

{

action;

[return int;]

}

说明:

  • 1、可以带function fun() 定义,也可以直接fun() 定义,不带任何参数。
  • 2、参数返回,可以显示加:return 返回,如果不加,将以最后一条命令运行结果,作为返回值。 return后跟数值n(0-255),函数返回值在调用该函数后通过 $? 来获得

函数参数

注意,$10 不能获取第十个参数,获取第十个参数需要${10}。当n>=10时,需要使用${n}来获取参数。

#!/bin/bash

funWithParam(){
echo "第一个参数为 $1 !"
echo "第二个参数为 $2 !"
echo "第十个参数为 $10 !"
echo "第十个参数为 ${10} !"
echo "第十一个参数为 ${11} !"
echo "参数总数有 $# 个!"
echo "作为一个字符串输出所有参数 $* !"
}
funWithParam 1 2 3 4 5 6 7 8 9 34 73
第一个参数为 1 !
第二个参数为 2 !
第十个参数为 10 !
第十个参数为 34 !
第十一个参数为 73 !
参数总数有 11 个!
作为一个字符串输出所有参数 1 2 3 4 5 6 7 8 9 34 73 !

bash脚本编程学习笔记_脚本_07

11.输入/输出重定向

需要注意的是文件描述符 0 通常是标准输入(STDIN),1 是标准输出(STDOUT),2 是标准错误输出(STDERR)。

bash脚本编程学习笔记_编程_08

/dev/null 文件

如果希望执行某个命令,但又不希望在屏幕上显示输出结果,那么可以将输出重定向到 /dev/null:

$ command > /dev/null

/dev/null 是一个特殊的文件,写入到它的内容都会被丢弃;如果尝试从该文件读取内容,那么什么也读不到。但是 /dev/null 文件非常有用,将命令的输出重定向到它,会起到"禁止输出"的效果。

如果希望屏蔽 stdout 和 stderr,可以这样写:

$ command > /dev/null 2>&1

这里的 2 和 > 之间不可以有空格,2> 是一体的时候才表示错误输出。

​12.文件包含

. filename   # 注意点号(.)和文件名中间有一空格



source filename

bash脚本编程学习笔记_脚本_09

#!/bin/bash

#使用 . 号来引用test1.sh 文件
. ./test1.sh

# 或者使用以下包含文件代码
# source ./test1.sh

echo "菜鸟教程官网地址:$url"

注:被包含的文件 test1.sh 不需要可执行权限


参考:​​https://www.runoob.com/linux/linux-shell.html​