介绍Bash之前首先介绍Shell,shell是一个程序,可以称之为壳程序,用于用户与操作系统进行交互。用来区别与核,相当于是一个命令解析器,Shell有很多中,这里列出其中几种 :
- Bourne SHell(sh)
- Bourne Again SHell(bash)
- C SHell(csh)
- KornSHell(ksh)
- zsh
各个shell的功能都差不太多,在某些语法的下达下面有些区别,Linux预设就是bash。
简单点说,直接把shell和bash先理解为一个东西好了,就是Linux中的那个终端窗口(Terminal),也就是那个小黑框,下面的例子都是在Linux的终端窗口中运行的。
变量
变量赋值
- 基本形式为
变量=变量值
,注意等号左右不能有空格,变量均为文本形式,如;
- 对于有空格的变量值,用单引号或双引号包围,如:
- 可以将某个命令输出的文本直接赋予某个变量,命令需要反引号包围,如:
- 变量之间可以赋值,需要使用**
$
符号**说明是变量,如:
- 可以使用**
read
关键字**接收数据至某个变量,如:
变量引用
变量引用是指将变量翻译为变量中存储的文本,基本形式为$变量
。
- 通过
echo
命令显示变量,如:
1
| 2019年 11月 10日 星期日 19:12:55 CST
|
- 通过
echo
显示时,可以直接与附加文本相连,如:
- 当附加文本尾随变量名造成歧义时,添加大括号,如;
- 可以在双引号内使用变量,但在单引号内只能被当作文本,如:
数学运算
- 在bash中,数字和运算符均被当作文本,数学运算需借助**双大括号
$(())
**:
1 2 3
| result=$((1+2)) echo $result
|
- 支持的运算符有:加
+
、减-
,乘*
,除/
,求余%
,乘方**
,其中乘方的优先级最高,示例:
1 2
| echo $((2+5*2**(5-3)/2))
|
返回代码
- 在Linux中,每个可执行程序运行完后会有一个整数的返回值,可以使用**
$?
变量**来接收,对于简单的foo.c
程序:
1 2 3 4 5 6 7
| int main(void) { int a=1; return 0; }
|
使用gcc编译器编译,并执行:
1 2 3 4
| gcc foo.c ./a.out echo $?
|
- 如果程序运行异常,将返回非0值,如删除一个不存在的文件:
1 2
| rm: cannot remove 'none_exist.file': No such file or directory
|
- 在执行多条指令时,可以让后一个程序的运行参考前一个程序的返回代码,如:
首先新建一个文件并查看确认:
成功删除的情况,使用**&&
符号**连接:
1 2
| rm demo.file && echo "rm succeed"
|
不成功删除的情况,使用**||
符号**连接:
1 2
| rm demo.file || echo "rm failed"
|
1 2 3
| rm: cannot remove 'demo.file': No such file or directory rm failed
|
bash脚本
脚本示例
使用vim编辑器编辑test.sh
文件,内容如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| #!/bin/bash
echo "Information of xxpcb's computer:" > log
echo "------lscpu---------------------" >> log lscpu >> log
echo "------uname -a------------------" >> log uname -a >> log
echo "------free -h-------------------" >> log free -h >> log
|
该文件的作用是将一些计算机信息保存到所在目录的log
文件中。
使用sh test.sh
执行bash脚本。
使用cat log
命令查看log文件信息:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| Information of xxpcb's computer: ------lscpu--------------------- Architecture: x86_64 CPU op-mode(s): 32-bit, 64-bit Byte Order: Little Endian CPU(s): 4 On-line CPU(s) list: 0-3 Thread(s) per core: 1 Core(s) per socket: 4 Socket(s): 1 NUMA node(s): 1 Vendor ID: GenuineIntel CPU family: 6 Model: 60 Model name: Intel(R) Core(TM) i5-4590 CPU @ 3.30GHz Stepping: 3 CPU MHz: 1512.460 CPU max MHz: 3700.0000 CPU min MHz: 800.0000 BogoMIPS: 6596.30 Virtualization: VT-x L1d cache: 32K L1i cache: 32K L2 cache: 256K L3 cache: 6144K NUMA node0 CPU(s): 0-3 Flags: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm cpuid_fault epb invpcid_single pti ssbd ibrs ibpb stibp tpr_shadow vnmi flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid xsaveopt dtherm ida arat pln pts md_clear flush_l1d ------uname -a------------------ Linux deeplearning 5.0.0-29-generic #31~18.04.1-Ubuntu SMP Thu Sep 12 18:29:21 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux ------free -h------------------- total used free shared buff/cache available Mem: 15G 939M 12G 29M 2.2G 14G Swap: 11G 0B 11G
|
可以看出CPU型号:i5-4590 CPU,Linux版本:Ubuntu18.04,内存容量:15G。
脚本参数
- bash脚本在运行时,也可以携带参数,在脚本中通过变量的形式接收,如
test_arg.sh
内容如下:
1 2 3 4 5 6
| #!/bin/bash
echo $0 echo $1 echo $2
|
其中$0
是命令的第一部分,$1
才是第一个参数,如运行:
1 2
| ./test_arg.sh hello world
|
1 2 3 4
| ./test_arg.sh hello world
|
- 利用传入的参数可以令脚本的使用更加灵活,对于上面的
test.sh
文件,可以使用参数指定保存的文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| #!/bin/bash
echo "Information of xxpcb's computer:" > $1
echo "------lscpu---------------------" >> $1 lscpu >> $1
echo "------uname -a------------------" >> $1 uname -a >> $1
echo "------free -h-------------------" >> $1 free -h >> $1
|
在执行时,可以指定将信息输出到output.file
文件:
脚本的返回值
与可执行程序类似,脚本也可以有返回值,按照惯例正常情况返回0,在脚本末尾使用exit命令设置返回值,如hello_world.sh
:
1 2 3 4 5 6
| #!/bin/bash
echo Hello echo World exit 0
|
注意,末尾手动添加exit 0
并不必要,脚本正常运行其实会自动返回代码0。执行示例:
注意,如果在脚本中间出现exit
,则脚本提前退出,并返回该exit命令给出的代码值。
函数
脚本中也可以使用类似函数的结构,并且同样可以使用传入的参数:
1 2 3 4 5 6 7 8 9 10 11 12 13
| #!/bin/bash
function my_info() { lscpu >> $1 uname -a >> $1 free -h >> $1 }
my_info output.file
|
注意:函数定义时,关键字function
和大括号{}
为函数提示,因而可以省略function
关键字。
跨脚本调用
使用source
命令可以实现函数的跨脚本调用。**source
命令**的作用是在同一个进程中执行另一个文件中的bash脚本。
例如有my_info.sh
(内容如上)和app.sh
:
1 2 3 4 5
| #!/bin/bash
source my_info.sh my_info output.file
|
运行app.h
,执行到source命令所在行时,就会执行my_info.sh
脚本。因此在app.h
中使用my_info
函数。
注:
/bin/sh
与/bin/bash
的细微区别(参考:https://www.cnblogs.com/givemelove/p/8477430.html)
在shell脚本的开头往往有一句话来定义使用哪种sh解释器来解释脚本。
目前研发送测的shell脚本中主要有以下两种方式:
所以,sh跟bash的区别,实际上就是bash有没有开启posix模式的区别