> For the complete documentation index, see [llms.txt](https://sugar-at.gitbook.io/blog-article/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://sugar-at.gitbook.io/blog-article/shell/1.md).

# 1. shell 变量与常见符号

## 变量

运行shell时，会同时存在三种变量：

1. 局部变量 局部变量在脚本或命令中定义，仅在当前shell实例中有效，其他shell启动的程序不能访问局部变量。
2. 环境变量 所有的程序，包括shell启动的程序，都能访问环境变量，有些程序需要环境变量来保证其正常运行。必要的时候shell脚本也可以定义环境变量。
3. shell变量 shell变量是由shell程序设置的特殊变量。shell变量中有一部分是环境变量，有一部分是局部变量，这些变量保证了shell的正常运行

### 声明即用

```bash
a=2
b="123"
```

调用 ${varName}或者 $varName

```bash
echo $b
echo ${a}
```

### 只读变量

```bash
param=123
readonly param
param=1
```

运行

```bash
./1.sh:行3: param: 只读变量
```

### 删除变量

```bash
unset varName
```

* unset不能删除只读变量
* 删除后不能再次使用

```bash
a=123
unset a
echo $a
```

运行

```
没有任何输出内容
```

## 传递参数

### 常见变量

* $?:判断上一个语句是否成功
* $0:执行脚本文件名称
* $1:第1个参数
* $n:第n个参数
* $\*:参数分别是什么
* $@:与 $\*相同，但是使用时加引号，并在引号中返回每个参数。
* $#:参数个数
* $$:脚本当前的进程号

### 传递参数示例

demo1.sh

```bash
echo "脚本文件名称:$0"
echo "第1个参数:$1"
echo "所有的参数:$*"
echo "参数个数:$#"
```

赋予执行权限

```
chmod u+x demo1.sh
```

执行

```bash
./demo1.sh param2 1 2 3
```

输出结果

```
脚本文件名称:./demo1.sh
第1个参数:param2
所有的参数:param2 1 2 3
参数个数:4
```

## 符号

### 常见符号

#### `>`  :向目标文件写入内容

* 会覆盖掉原来的内容
* 例子:向文件1.txt写入hello world字符串

  ```bash
    # 直接在bash中可运行
    echo hello world > 1.txt
  ```

#### `>>` :向目标文件尾部插入内容

* 在源文件尾部追加内容
* 例子:向文件1.txt增加一行hello world字符串

  ```bash
    # 直接在bash中可运行
    echo hello world >> 1.txt
  ```

#### `;` :执行多条指令

* 例子:追加一行内容,然后显示文件当前的内容

  ```bash
    # 直接在bash中可运行
    echo hello world >> 1.txt ; cat 1.txt
  ```

#### `|` :管道符

* 将上一条命令的处理结果传给下一个命令处理
* 例子:将cat结果传给wc命令统计行数

  ```bash
    # 直接在bash中可运行
    # 最后一个字母为小写的L
    cat 1.txt | wc -l
  ```

#### `&&` :执行多条命令

* 前一条命令出错,会阻塞后续命令执行
* 例子:向1.txt追加一行内容 再查看其行数

  ```bash
    # 直接在bash中可运行
    echo str >> 1.txt && wc -l 1.txt
  ```

#### `||` :执行多条命令

* 前一条命令出错才会执行后续指令
* 例子:向1.txt追加一行内容出错 ,再查看其内容

  ```bash
    # 直接在bash中可运行
    echo3 str >> 1.txt || cat 1.txt
  ```

#### `""` :能够输出变量值

* 能够解析字符串中的 $varName 变量
* 例子:输出hello

  ```bash
  # 编写demo3.sh

    a="hello"
    echo "$a"
  ```

#### `''` :不能够输出变量值

* 不够解析字符串中的 $varName 变量
* 例子:不能输出hello

  ```bash
  # 编写demo3.sh

    a="hello"
    echo '$a'
  ```

  输出结果为:$a

#### ` `` ` :输出命令结果

* 例子:输出当前的日期
* date命令可获取当前日期

  ```bash
  echo `date`
  ```

#### `2>/dev/null` :错误输出到无底洞

* 命令执行错误则不会出现错误提示
* 执行正确才会有输出结果
* 例子

  ```bash
  # 执行
  echo1 123
  # 正常错误输出
  bash: echo1: 未找到命令
  # 使用无底洞
  echo1 123 2>/dev/null
  # 没有任何内容输出
  ```

#### `1>/dev/null` :正确输出到无底洞

* 命令执行正确则不显示执行结果
* 执行错误才会有错误提示内容&#x20;
* 例子

  ```bash
  # 执行
  echo 123
  # 正常输出
  123
  # 使用无底洞
  echo 123 1>/dev/null
  # 没有任何内容输出
  ```

## 字符串

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

### 单引号

```bash
str='hello world $$ $a'
echo $str
```

输出

```
hello world $$ $a
```

* 单引号里的任何字符都会原样输出
* 变量无效
* 不能单独出现一个引号(加上反斜杠转义也不行),只能成对出现
* 可用于字符串拼接

### 双引号

```bash
str='sugar'
echo "my name is $str"
```

输出

```
my name is sugar
```

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

### 字符串拼接

```bash
name="sugar"
str1="hello, "$name" !"
str2="hello, $name !"
str3='hello, '$name' !'
str4='hello, $name !'
echo $str1
echo $str2
echo $str3
echo $str4
```

输出

```
hello, sugar !
hello, sugar !
hello, sugar !
hello, $name !
```

### 获取字符串长度

```bash
str="abcdefg"
echo "${#str}"
```

输出

```
7
```

### 截取字符串

```bash
str="hello world"
echo ${str:2:4}
```

输出

```
llo
```

## 数组

* 只支持一维数组
* 没有限定数组大小
* 可以不使用连续的下标，而且下标的范围没有限制。

### 数组声明格式

```bash
arrName=(v0 v1 v2 v3)
```

等价

```bash
arrName=(
  v0
  v1
  v2
  v3
)
```

等价

```
arrName[0]=v0
arrName[1]=v1
arrName[2]=v2
arrName[3]=v3
```

### 数组调用格式

```bash
${arrName[index]}
```

读取所有元素

```bash
${arrName[@]}
```

### 数组长度

```bash
length=${#arrayName[@]}
# 或者
length=${#arrayName[*]}
```

### 数组使用示例

```bash
arr1=(1 2 3 4 5)
arr2=("A" 'b' 'c' 3)
arr3=(
 1
 2
 3
)

echo "${arr1[0]}"
echo ${arr2[1]}
echo ${arr3[2]}

echo  "arr1长度为:${#arr1[*]}"
echo  "arr2长度为:${#arr2[@]}"
```

运行输出

```
1
b
3
arr1长度为:5
arr2长度为:4
```
