1
#!/bin/bash

echo是用于终端打印的最基本命令。echo在每次调用后会添加一个换行符。

可以使用双引号、单引号或者不用引号。

双引号允许shell解释字符串中出现的特殊字符。单引号不会对其做任何解释。

1
echo "welcom to bash"

printf也是终端打印的命令,但并不会自动添加换行符

获取应用程序的进程ID:

1
pgrep mysql

查看该进程相关的环境变量:

1
2
3
4
# cat /proc/$PID/environ
cat /proc/3081636/environ
# 易于读取
cat /proc/2666448/environ | tr '\0' '\n'

PATH变量列出了一系列可供shell搜索特定应用程序的目录,各目录路径之间以:分隔。

$PATH通常定义在/etc/environment、/etc/profile或~/.bashrc中。

1
2
3
4
5
echo $PATH
# 输出
"""
/usr/local/apache-maven-3.6.3/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/usr/local/nginx/sbin:/opt/jdk/jdk-11.0.7/bin:/root/bin
"""

在 PATH 中添加一条路径:

1
export PATH="$PATH:/home/user/bin"

其他的环境变量:HOME、PWD、USER、UID、SHELL

root用户的UID是0

数学运算

Bash shell使用let、(( ))和[]执行基本的算术操作。工具expr和bc可以用来执行高级操作。

也可以使用操作符(())。出现在(())中的变量名之前需要加上$:

bc是一个用于数学运算的高级实用工具,这个精密的计算器包含了大量的选项。我们可以借助它执行浮点数运算并使用一些高级函数

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
36
37
38
39
40
41
42
43
44
45
46
#!/bin/bash
no1=4;
no2=5
let result=no1+no2;
echo $result;
let no1++;
let no2--;
echo $no1;
echo $no2;

let no1+=6;
let no2-=6;
echo $no1;
echo $no2;

result=$[no1+no2];
echo $result;

# 也可以使用操作符(())。出现在(())中的变量名之前需要加上$:
result=$((no1+5));
echo $result;

# expr同样可以用于基本算术操作
result= expr 3+4;
echo $result;
echo "------------------";

echo "4 * 0.56" | bc;

no=54
result='echo "$no * 1.5" | bc';
echo $result;

# bc是一个用于数学运算的高级实用工具,这个精密的计算器包含了大量的选项。我们可以借助它执行浮点数运算并使用一些高级函数
# 设置小数精确度,通过参数scale=2,将保留2位小数
echo "scale=2;22/7" | bc;

# 进制转换
no=100
echo "obase=2;$no" | bc
no=1100100
echo "obase=10;ibase=2;$no" | bc;

# 计算平方和算术平方根
echo "sqrt(100)" | bc;
echo "10^10" | bc;

文件描述符与重定向

文件描述符与输入输出流相关联的整数,最广为人知的文件描述符是stdinstdoutstderr

stdin:标准输入

stdout:标准输出

stderr:标准错误

文件描述符是与某个打开的文件或数据流相关联的整数。

文件描述符0、1以及2是系统预留的。

❏ 0 —— stdin(标准输入)。

❏ 1 —— stdout(标准输出)。

❏ 2 —— stderr(标准错误)。

1
2
3
4
5
6
$ ls +
# 输出:ls: cannot access '+': No such file or directory
# 将错误信息输出到文件err.txt
$ ls + 2>err.txt
cat err.txt
# ls: cannot access '+': No such file or directory

1、使用 > 大于号,将文本保存至文件中

1
echo "I have a djungarian hamster" > temp.txt

2、使用 >> 双大于号,将文本追加到文件中。

1
echo "his name is nm" >> temp.txt

3、cat 查看文件

1
cat temp.txt

当一个命令发生错误并退回时,它会返回一个非0的退出状态;

而当命令成功完成后,它会返回为0的退出状态。

退出状态可以从特殊变量$?中获得(在命令结束之后立刻运行echo $?,就可以打印出退出状态)。

4、tee命令

tee命令从stdin中读取,然后将输入数据重定向到stdout以及一个或多个文件中。

1
command | tee file1 file2 | otherCommand

tee命令会将文件覆盖,但它提供了一个-a选项,可用于追加内容

1
cat a* | tee -a out.txt | cat -n

注意:

1、重定向输出针对的是标准输出,如果要使用文件描述符,必须将文件描述符放在操作符之前。

等同于1>;对于>>来说,情况也类似(即>>等同于1>>)

2、null设备通常也被称为黑洞,./dev/null是一个特殊的设备文件,它会丢弃接收到的任何数据

3、将文件重定向到命令,使用小于号<

1
cmd < file

4、<操作符 可以将文件读入stdin。

>操作符用于截断模式的文件写入,数据直接覆盖文件中的内容。

>>操作符用于追加模式的文件写入。

文件描述符可以用以上3种模式中的任意一种来创建。

索引数组和关联数组

Bash从4.0版本才开始支持关联数组。

相关练习

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
36
37
38
39
40
41
42
43
#!/bin/bash
############# 索引数组 #############
# 定义数组
# 1、单行
arr1=(a1 a2 a3 a4 a5)
arr2[0]="a21"
arr2[1]="a22"
arr2[2]="a23"

# 输出数组全部内容
echo ${arr1[*]} # 输出数组全部内容, a1 a2 a3 a4 a5
echo ${arr1[@]} # a1 a2 a3 a4 a5

# 输出单个元素
echo ${arr1[2]} # 输出单个,a3
index=4
echo ${arr1[$index]} # a5

# 数组长度
echo ${#arr2[*]} # 3

echo ${!arr1[@]} # 0 1 2 3 4
echo "***************"

############# 关联数组 #############
# 1、将变量声明为关联数组
declare -A ass_arr

# 2 添加元素
# 2.1 使用行内"索引-值"
ass_arr=([dog]=2500 [cat]=1500 [mouse]=40)
# 2.2 使用独立的"索引-值"
ass_arr[alpaca]=3000

# 3、显示数组内容
echo "dog needs ${ass_arr[dog]}" # dog needs 2500

# 4、列出数组索引
# 4.1
echo ${!ass_arr[*]} # alpaca mouse cat dog
# 4.2
echo ${!ass_arr[@]} # alpaca mouse cat dog
# ${!arr1[@]} 对于普通索引数组也可行

别名

使用alias命令创建别名

1、创建别名

1
alias new_command='command sequence'

示例:

1
2
# 将查看test1.sh文件命令,重命名为catt
alias catt='cat test1.sh'

alias命令的效果只是暂时的,

2、设置每次登录,别名都可用

修改~/.bashrc文件,添加别名命令,然后执行source ~/.bashrc,使其生效。

1
2
3
4
5
6
7
8
9
vim ~/.bashrc

#echo 'alias lll="ll"' >> ~/.bashrc
alias lll="ll"

source ~/.bashrc

# 查看
lll

3、删除别名,使用unalias命令

1
unalias lll

注意:如果别名已存在,则新的别名将覆盖旧别名

4、查看已存在的别名列表

alias 命令或者alias -p命令

5、别名转义

如果身份为特权用户,别名也会造成安全问题。

字符\可以转义命令,从而执行原本的命令。

1
\command

终端信息

tputstty是两款终端处理工具。

1、获取终端的行数和列数:

1
2
tput lines # 行
tput cols # 列

2、打印出当前的终端名

1
tput longname

3、将光标移动到坐标(50,50)处

1
tput cup 5050

6、设置终端背景色tput setb n,前景色tput setf n,n 为0~7数字

image-20210727141846967

7、stty -echo 禁止将输出发送至终端,stty echo 允许将输出发送至终端

1
2
3
4
5
6
7
8
9
10
11
#!/bin/bash
# filename:password.sh
echo -e "请输入密码:"
# 读取密码前禁止回显
stty -echo
read password
#重新允许回显
echo
echo Password read
# stty -echo 禁止将输出发送至终端
# stty echo 允许将输出发送至终端

8、设置文本粗体:tput bold

设置下划线起止:tput smultput rmul

删除当前光标到行尾的内容:tput ed

tput clear 清屏

tput sc保存当前位置

tput rc # 显示输出

时间日期及延时

1、读取日期

1
2
3
4
5
6
7
8
$ date
Tue Jul 27 15:19:47 CST 2021

$ date +%s
1627370446

$ date --date "2008-12-12" +%s
1229011200

2、测试代码和命令执行所花费时间

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#!/bin/bash
start=$(date +%s)
echo $start
#commands;
#statements;
a=1000
b=2000
c=a+b
echo c

end=$(date +%s)
echo $end

diff=$((end-start))
echo "time tike to execute commands is $diff seconds"

date的最小精确度为秒,还可以使用命令time Command/ScriptName计算

1
time ls

image-20210727153015470

3、使用sleep命令延时

sleep命令可以延迟脚本执行一段时间(以秒为单位)

示例:下面的脚本使用tputsleep从0开始计时到40秒

1
2
3
4
5
6
7
8
9
10
11
12
#!/bin/bash
echo count:
tput sc # 保存当前光标位置

# 循环40s
for count in `seq 0 40`
do
tput rc # 显示输出
tput ed # 删除当前光标到行尾的内容
echo -n $count
sleep 1
done

调试脚本

1、Bash内建

1
2
3
bash -x script.sh
#
sh -x script.sh

其中文件script.sh

1
2
3
4
5
6
7
8
9
#!/bin/bash
for i in {1..10}
do
set -x
echo $i
set +x
done
echo "script executed"
# 使用-x和+x对调试区域进行了限制。

❏ set -x:在执行时显示参数和命令。

❏ set+x:禁止调试。

❏ set -v:当命令进行读取时显示输入。

❏ set+v:禁止打印输入。

2、自定义调试信息,_DEBUG环境变量

1
2
3
4
5
6
7
8
9
10
#!/bin/bash
echo $_DEBUG;

function DEBUG(){
["$_DEBUG"=="on"]&& $@ || :
}
for i in {1..10}
do
DEBUG echo "I is $i"
done

执行_DEBUG=on ./debug.sh

3、shebang的妙用

把shebang从#!/bin/bash改成 #!/bin/bash -xv

1
2
# 将错误信息输出到文件debugout.txt
$ _DEBUG=on sh -x debug.sh 2 > debugout.txt
作者

Fahsa

发布于

2021-11-01

更新于

2021-11-01

许可协议

评论