shell脚本基础

shell 脚本的关键在于输入多个命令 并 处理每个命令的结果, 甚至需要将一个命令的结果传给另一个命令.

1 使用多个命令

将多个命令放在一行, 用分号 “;” 分隔, 就可以让多个命令串行执行了:

$ date
Fri Sep  3 23:51:38 CST 2021

$ who
miyan    pts/6        Sep  3 00:27 (112.65.13.166)

$ date; who
Fri Sep  3 23:51:49 CST 2021
miyan    pts/6        Sep  3 00:27 (112.65.13.166)

2 创建 shell 脚本文件

创建 shell 脚本文件时, 必须在 文件的第一行指定的要使用的 shell.
其格式为:
#!/bin/bash
在 shell 脚本中, 井号(#) 用于注释一行. 然而在 shell 脚本的第一行是个例外, # 后面的 ! 表明用哪个 shell 来运行脚本, 可以用 bash, zsh 等等.

第一个 shell 脚本(脚本名为 temp.sh):

#!/bin/bash
# 日期, 登录用户
date
who

执行:

$ temp.sh
zsh: command not found: temp.sh

报错了!!! 这是因为 shell 是通过 PATH 环境变量的路径来查找命令的, 我写的 temp.sh 不在 PATH 路径中:

$ echo $PATH
/usr/local/apache-maven-3.6.3/bin:/usr/local/bin:/usr/bin:/home/miyan/bin:/usr/local/sbin:/usr/sbin:/data/soft/zookeeper/bin

有两种方法可以执行 temp.sh 脚本:

  1. temp.sh 所在的目录添加到 PATH 环境变量中.
  2. 绝对路径相对路径 执行 temp.sh.

一般都是用 相对路径 执行 shell 脚本, 下面展示了用 相对路径绝对路径 执行 temp.sh 脚本:

$ chmod +x temp.sh

$ ./temp.sh
Sat Sep  4 00:23:46 CST 2021
miyan    pts/6        Sep  4 00:12 (112.65.13.166)

$ /home/miyan/test/temp.sh
Sat Sep  4 00:24:06 CST 2021
miyan    pts/6        Sep  4 00:12 (112.65.13.166)

默认情况下, 新建的文件是没有执行权限的(和 umusk 配置有关), 所以需要用 chmod 先加上执行权限 x.

3 显示消息

大多数 shell 命令都会产生自己的输出.
如果需要自己输出指定的文本信息, 需要使用 echo 命令.
比如:

$ echo this is a echo test
this is a echo test

$ echo let's see if this'll work
lets see if thisll work

$ echo "let's see if this'll work"
let's see if this'll work

echo 使用单引号 ' 或 双引号 " 来划定文本字符串, 如果在字符串中用到 '" 的一种, 你 必须 使用另外一种把它包起来.

echo 默认输出的文本会 换行. 如果不想 换行, 可以使用 -n 参数实现 不换行 :

$ cat temp.sh
#!/bin/bash
echo -n "当前显示时间: "
date

$ ./temp.sh
当前显示时间: Sat Sep  4 00:40:06 CST 2021

4 使用变量

4.1 环境变量

在脚本中, 只要在 环境变量名 前加上 $ 就能够使用 环境变量的值.
这和在命令行中使用没有区别:

$ echo $USER
miyan

$ echo $HOME
/home/miyan

4.2 用户变量

可以在 shell 脚本种自定义变量, 这种自定义的变量就是 用户变量.

注意:

  1. 用户变量名 是大小写敏感的
  2. 用户变量名 只能有 字母, 数字, 下划线 组成, 且不能以数字开头.
  3. 使用等号(=)给用户变量赋值时, 在 变量名= 三者之间, 不能出现空格!!!
  4. 不需要指定变量类型, shell 会自动决定变量的 数据类型.
  5. 用户变量 和 环境变量 一样, 也用 $ 引用.
  6. 引用变量需要 $, 而对变量赋值时不需要 $.

示例:

$ cat temp.sh
#!/bin/bash
days=10
guest="miyan"
echo "$guest checked in $days days ago"

days=3
guest="rosie"
echo "$guest checked in $days days ago"

value1="hello world"
value2=value1
value3=$value1
echo "value2: '$value2', value3: '$value3'"

执行结果:

$ ./temp.sh
miyan checked in 10 days ago
rosie checked in 3 days ago
value2: 'value1', value3: 'hello world'

注意到,
value2 被赋予的是 value1 字符串;
value3 被赋予的是 hello world($value1的值)字符串.
所以, 没有 $, shell 会把变量名解释成 普通的字符串.

shell 数组变量示例:

$ cat temp.sh
#!/bin/bash
# 方式一
test_array_a=(1 2 3)
#方式二
test_array_b[0]=1
test_array_b[1]=2
test_array_b[2]=3

for i in ${test_array_a[@]}; do
    echo "$i"
done
for i in ${test_array_b[@]}; do
    echo "$i"
done


$ ./temp.sh
1
2
3
1
2
3

定义数组有两种方式:
1, 用括号来表示, 元素用"空格"符号分割开, 语法格式如下:
array_name=(value1 value2 ... valuen);
2, 使用下标来定义数组, 语法格式如下:

array_name[0]=value0
array_name[1]=value1
array_name[2]=value2

获取 shell 数组单个下标为 index 的元素: ${array_name[index]};
获取 shell 数组中的所有元素: ${my_array[*]}${my_array[@]}.

4.3 命令替换

命令替换: 把命令的输出信息提取出来.

有两种方法可以实现命令替换:

  1. 反引号字符 `
  2. $() 格式

示例:

$ echo "现在时间是: $(date)"
现在时间是: Sat Sep  4 01:13:25 CST 2021

$ echo "现在时间是: `date`"
现在时间是: Sat Sep  4 01:13:48 CST 2021

如上所示, 把 date 命令的输出提取出来, 放在 echo 命令中显示.

命令替换 通常用于给 变量赋值.

5 重定向输入和输出

5.1 输出重定向

如果想要 把命令的输出 重定向(保存)到文件中, 而不是显示在标准输出(显示器)上, 则需要用到 输出重定向.

输出重定向的使用方法:
command > outputFile

输出重定向符号有>>> 两个:

  1. 操作符>, 把输出重定向到文件, 如果文件已经存在, 则会覆盖原文件.
  2. 操作符>>, 如果文件已经存在, 会追加数据, 不会覆盖原文件的数据.

示例:

$ echo "hello world" > test
$ cat test
hello world

$ whoami >> test
$ cat test
hello world
miyan

5.2 输入重定向

输入重定向 与 输出重定向 相反, 输入重定向 将文件的内容重定向到命令.
输入重定向的使用方法:
command < inputFile

输入重定向符号有<<< 两个.
< 用于把文件的内容重定向到命令:

$ echo "hello" > test
$ wc -l < test
1

$ echo "world" >> test
$ wc -l < test
2

<<内联输入重定向(inline input redirection), 它不是把文件的内容重定向到命令, 而是把 命令行指定的输入 重定向到命令. 使用 << 时, 必须使用一个 文本标记(可以是任一字符串, 一般时 EOF) 来标记 输入内容的开始和结尾.
示例:

$ wc -l << EOF
heredoc> hello
heredoc> world
heredoc> EOF
2

上面的 heredoc> 这个标记用于提示我们继续输入字符串, 当我们输入第二个 EOF 后, 表示输入结束, 然后 wc 命令开始执行.

6 管道

管道: 把一个命令的输出 作为 另一个命令的输入.

管道符号: |.

管道的使用方法, 把 command1 的输出 作为 command2 的输入:
command1 | command2

注意, 管道| 连接的两个命令并不是依次执行的, Linux 系统会同时运行两个命令, 在第一个命令产生输出的同时, 输出会立即送到第二个命令. 其中不会有任何中间文件和缓冲区.
管道|使用示例, 查看当前目录下的文件和目录所占的磁盘空间大小, 并按降序排列:

du -sh * | sort -hr

管道的功能也可以用 重定向 来实现:

$ du -sh * > test
$ sort -hr < test

7 执行数学运算

这里简单介绍一下 整数运算, 浮点数运算bc 命令实现, 这里不涉及.

expr 命令是 Bourne shell 提供的处理 数学表达式(expression) 的命令.
expr 真不好用, 看示例:

$ expr 2+5
2+5
$ expr 2 + 5
7

$ expr 2 * 5
expr: syntax error
$ expr 2 \* 5                                                                                                                                                
10

可以看到, expr 要求运算符两边必须有空格, * 需要转义(防止被解释成通配符).

bash shell 为了保持和 Bourne shell 兼容而包含了 expr 命令, 但同时 bash 提供了一种更简单的方法执行 数学表达式.
可以用美元符 $ 和 方括号[] 把数学表达式包起来:
$[ operation ]

示例:

$ echo $[2+5]
7
$ echo $[2*5]
10

8 退出脚本

shell 中运行的每一个命令都是使用 退出状态码(exit status) 告诉 shell 它是否已经执行完毕.
exit status 是一个 0~255 的整数值, 在命令结束运行时 由命令传给 shell. 可以捕获这个值并在脚本中使用.

8.1 查看退出状态码

Linux 提供了一个专门的变量 $? 保存上一个已执行的命令的 退出状态码(exit status). 对于需要检查的命令, 必须 在其运行完毕后立刻 查看 $? 变量:

$ date
Sat Sep  4 12:02:51 CST 2021
$ echo $?
0

exit status 为 0 表示命令成功结束.
如果命令结束时报错, 那么 exit status 就是一个正数值:

$ hellomiyan
zsh: command not found: hellomiyan
$ echo $?                                                                                                                                                        
127

Linux 的一些 退出状态态 可以参考下表:

退出状态码描述
0命令成功结束
1一般性未知错误
2不适合的shell命令
126命令不可执行
127没找到命令
128无效的退出参数
130通过 ctrl+c 终止命令
255正常范围之外的退出状态码

8.2 exit 命令

默认情况下, shell 脚本会以 最后一个命令的退出状态码 退出.
示例:

$ cat temp.sh
#!/bin/bash
echo "math expression:"
echo "2 + 5 = $[2+5]"

$ ./temp.sh
math expression:
2 + 5 = 7

$ echo $?
0

我们可以使用 exit 命令, 返回自己的 退出状态码:

$ cat temp.sh
#!/bin/bash
echo "math expression:"
exit 1
echo "2 + 5 = $[2+5]"

$ ./temp.sh
math expression:

$ echo $?                                                                                                                                                         
1

可以看到, exit 命令执行以后, 就退出脚本了, exit 后面的命令不会被执行.

Reference

[1]. Linux命令行与shell脚本编程大全(第三版)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值