Shell 学习过程中的一些记录

变量

变量定义

变量名与值使用一个等号 ‘=’ 连接

1
$country=china

等号两边不能存在空格

1
2
$country =china  # country: command not found
$country= china  # country: command not found

变量名不能以数字开头,不能出现空格或标点符号

1
$2country=china  # 2country=china:未找到命令

变量可以重复赋值

1
2
3
$foo=1
$foo=2
$echo $foo # 2

使用 declare 命令声明一些特殊类型的变量

常用参数:

  • -a 声明数组变量
  • -i 声明整数变量
  • -x 声明环境变量
  • -r 声明只读变量
1
2
3
4
$sum=1+2+3
$echo $sum # 1+2+3 (shell默认变量类型为字符串)
$declare -i sum=1+2+3
$echo $sum # 6

变量调用

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
$var_1=3
# 第一种方式 ${variable} (常用)
$echo ${var_1} # 3
# 第二种方式 $variable
$echo $var_1 # 3

# 计算变量长度
# 第一种方式 ${variable}
$echo ${#var_1} # 25
# 第二种方式
$len=`expr length "$var_1"`
$echo $len # 25

变量删除

一个伪概念,因为shell中对于未定义的变量一律返回空

因此删除一个变量有如下三种方法:

1
2
3
$unset variable
$variable=''
$variable=

输出变量

用户创建的变量仅可用于当前 Shell, 子 Shell 默认读取不到父 Shell 定义的变量。 为了把变量传递给子 Shell,需要使用export命令。 这样输出的变量,对于子 Shell 来说就是环境变量。

1
2
3
4
5
6
7
8
$foo=2
$bash        # 新建子shell
$echo $foo   # 返回空
$exit        # 退出子shell
$export foo  # 输出变量,使其变为当前shell的环境变量
$bash        # 新建子shell
$echo $foo   
2

子 shell 对变量的修改不影响父 Shell

1
2
3
4
5
6
$export foo=2
$bash        # 新建子shell
$echo $foo   # 2
$foo=3       # 在子shell重新赋值
$exit        # 退出子shell
$echo $foo   # 2

脚本参数传递

  • $0 当前 Shell 的名称或者脚本名
  • $1~$n 获取传入的参数
  • $# 传递到脚本的参数数量
  • $$ 当前 Shell 的 PID,可以用来命名临时文件
  • $* 以一个单字符串显示所有向脚本传递的参数
  • $? 上一个命令的退出码,0表示成功返回,其他任何值表明有错误
1
2
3
4
5
6
7
8
9
$ls notexist    # ls: 无法访问 'notexist': 没有那个文件或目录
$echo $?        # 2 错误码不固定
$echo $?        # 0 上一个命令成功返回了,因此返回0

$echo $$        # 13597 当前shell的pid
$tempfile=tempfile.$$
$echo $tempfile # tempfile.13597

$echo $0        # bash

新建一个 test.sh 文件,写入如下内容

1
2
3
#!/bin/bash
echo "Hello World"
echo $0

执行一下

1
2
3
$bash ./test.sh
Hello World
./test.sh

命令替换

两种形式

  • 反引号 `command`
  • $(command)
1
2
3
4
5
$echo date # date
# `command` 使用反引号将变量包起来
$echo `date +%Y` # 2021
# $(command)
$echo $(date)   # 2021年 4月21日 星期三 00时44分02秒 CST

数学运算

使用双括号进行整数运算

1
2
3
# (( )) 使用双括号将数学运算包起来
$echo $((20+30))
50

算术运算

  • -eq 相等
  • -ne 不相等
  • -gt 大于
  • -lt 小于
  • -ge 大于等于
  • -le 小于等于
1
2
3
4
$a=10
$b=20
$ if [ $a -eq $b ];then echo "true";else echo "false";fi
false

空格

  • shell中使用空格区分不同的参数
  • 如果参数之间有多个空格,shell会自动忽略
1
2
$echo this is a     test
this is a test

引号

  • 单引号包裹的内容会原样输出
  • 双引号仍然可以保留变量内容
  • 反引号:上面所说的命令替换
1
2
3
4
5
6
7
8
$country=china
$mycountry="mycountry is $country"
$echo $mycountry
mycountry is china  # 双引号仍然可以保留变量内容

$mycountry='mycountry is $country'
$echo $mycountry
mycountry is $country # 单引号包裹的内容会原样输出

标准输入输出(重定向)

1
2
3
标准输入   (stdin) :代号为 0 ,使用 < 或 << 表示
标准输出   (stdout):代号为 1 ,使用 > 或 >> 表示
标准错误输出 (stderr):代号为 2 ,使用 2> 或 2>> 表示

其中,> 或 < 表示清空并写入,> > 或 < < 表示追加写入

标准输出,即指令执行后返回的正确信息

标准错误输出,即指令执行失败后返回的信息

标准输入,则是将原本需要由键盘输入的信息,改为通过文件内容输入

 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
$ ps a  # 直接执行这个指令会输出如下标准输出
   PID TTY      STAT   TIME COMMAND
    25 pts/0    Ss     0:00 -bash
   344 pts/0    R+     0:00 ps a
$ ps a > ps.txt # 执行这个指令,原本应该在命令行输出的内容,会被保存到ps.txt文件中
$
$ cat ps.txt
   PID TTY      STAT   TIME COMMAND
    25 pts/0    Ss     0:00 -bash
   344 pts/0    R+     0:00 ps a
$ ps a 2> pserr.txt # 执行这个指令,因为只会将错误返回重定向,所以还是会输出下面的信息
   PID TTY      STAT   TIME COMMAND
    25 pts/0    Ss     0:00 -bash
   344 pts/0    R+     0:00 ps a

$ ps i 2> pserr.txt # ps命令没有 i 参数,所以直接执行会报错,使用 2> 可以将错误信息重定向到文件,因此终端看不到返回
$ cat pserr.txt
error: unsupported SysV option

Usage:
 ps [options]

 Try 'ps --help <simple|list|output|threads|misc|all>'
  or 'ps --help <s|l|o|t|m|a>'
 for additional help text.

$ ps i > pserr.txt # > 只能重定向正确返回,所以错误信息会直接返回在终端
error: unsupported SysV option

Usage:
 ps [options]

 Try 'ps --help <simple|list|output|threads|misc|all>'
  or 'ps --help <s|l|o|t|m|a>'
 for additional help text.

下面看一下标准输入的应用场景

1
$ mysql -uroot -p123456 < schema.sql

连接数据库之后,执行 schema.sql 文件中的语句