shell-2.变量

文件处理三剑客 grep awk sed

翻译自:
https://www.bilibili.com/video/BV1st411N7WS/?p=33&spm_id_from=pageDriver&vd_source=867fa98b57c5df7e6cb7e8f3ad59fd84

1. shell介绍

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

1. 编程语言分类

编译型语言:
程序在执行之前需要一个专门的编译过程,把程序编译成为机器语言文件,运行时不需要重新翻译,直接使用编译的结果就行了。程序执行效率高,依赖编译器,跨平台性差些。如C、C++

  • 解释型语言:

​ 程序不需要编译,程序在运行时由**解释器**翻译成机器语言,每执行一次都要翻译一次。因此效率比较低。比如Python/JavaScript/ Perl /ruby/Shell等都是解释型语言。

总结:

编译型语言比解释型语言速度较快,但是不如解释型语言跨平台性好。如果做底层开发或者大型应用程序或者操作系开发一般都用编译型语言;如果是一些服务器脚本及一些辅助的接口,对速度要求不高、对各个平台的兼容性有要求的话则一般都用解释型语言
在这里插入图片描述

2. shell种类

[root@MissHou ~]# cat /etc/shells 
/bin/sh				#是bash的一个快捷方式
/bin/bash			#bash是大多数Linux默认的shell,包含的功能几乎可以涵盖shell所有的功能
/sbin/nologin		#表示非交互,不能登录操作系统
/bin/dash			#小巧,高效,功能相比少一些

/bin/csh				#具有C语言风格的一种shell,具有许多特性,但也有一些缺陷
/bin/tcsh			#是csh的增强版,完全兼容csh

shell脚本能干啥?

①自动化软件部署 LAMP/LNMP/Tomcat…

②自动化管理 系统初始化脚本、批量更改主机密码、推送公钥…

自动化分析处理 统计网站访问量

自动化备份 数据库备份、日志转储…

⑤自动化监控脚本

shell脚本的基本写法

1)脚本第一行,魔法字符==#!==指定解释器【必写

#!/bin/bash 表示以下内容使用bash解释器解析

注意:
如果直接将解释器路径写死在脚本里,可能在某些系统就会存在找不到解释器的兼容性问题,所以可以使用:#!/bin/env 解释器 #!/bin/env bash

2)脚本第二部分,注释(#号)说明,对脚本的基本信息进行描述【可选】

#!/bin/env bash

# 以下内容是对脚本的基本信息的描述
# Name: 名字
# Desc:描述describe
# Path:存放路径
# Usage:用法
# Update:更新时间

#下面就是脚本的具体内容
commands
...

!/bin/bash 和 !/bin/env bash 的区别是!/bin/bash 指定bash解释器,而 !/bin/env bash 会自动选择当前环境的解释器

3)脚本第三部分,脚本要实现的具体代码内容

3.脚本执行方式

标准脚本执行方法(建议)

1) 编写人生第一个shell脚本
[root@MissHou shell01]# cat first_shell.sh
#!/bin/env bash

# 以下内容是对脚本的基本信息的描述
# Name: first_shell.sh
# Desc: num1
# Path: /shell01/first_shell.sh
# Usage:/shell01/first_shell.sh
# Update:2019-05-05

echo "hello world"
echo "hello world"
echo "hello world"

2) 脚本增加可执行权限
[root@MissHou shell01]# chmod +x first_shell.sh

3) 标准方式执行脚本
[root@MissHou shell01]# pwd
/shell01
[root@MissHou shell01]# /shell01/first_shell.sh
或者
[root@MissHou shell01]# ./first_shell.sh

注意:标准执行方式脚本必须要有可执行权限。

非标准的执行方法(不建议)

  1. 直接在命令行指定解释器执行
[root@MissHou shell01]# bash first_shell.sh
[root@MissHou shell01]# sh first_shell.sh
[root@MissHou shell01]# bash -x first_shell.sh
+ echo 'hello world'
hello world
+ echo 'hello world'
hello world
+ echo 'hello world'
hello world
----------------
-x:一般用于排错,查看脚本的执行过程
-n:用来查看脚本的语法是否有问题
------------

我以前经常采用sh xxx.sh的方式执行,这种方式,是非标准的执行方式,shell脚本即使没有可执行权限,sh xxx.sh的方式依然可以执行

所以以后要改为绝对路径或者相对路径的方式执行(标准方式执行),且标准方式执行,要求shell脚本必须有可执行权限

当我们对shell脚本没有执行权限的时候,可以采用非标准方式执行
2. 使用source命令读取脚本文件,执行文件里的代码

[root@MissHou shell01]# source first_shell.sh
hello world
hello world
hello world

**小试牛刀:**写一个木有灵魂的脚本,要求如下:

  1. 删除/tmp/目录下的所有文件

  2. 然后在/tmp目录里创建3个目录,分别是dir1~dir3

  3. 拷贝/home/yanweiling下的所有内容到刚创建的dir1目录里

  4. 最后打印"报告首长,任务已于2019-05-05 10:10:10时间完成"内容

    echo "报告首长,任务已于$(date +'%F %T')"

[root@node2 shell101]# vi first.sh
[root@node2 shell101]# chmod +x first.sh 
[root@node2 shell101]# ./first.sh 
报告首长,任务已于2022-10-19 11:05:14时间完成
[root@node2 shell101]# 
rm -rf /tmp/*
mkdir /tmp/dir{1..3}
cp -r /home/yanweiling/* /tmp/dir1
echo "报告首长,任务已于$(date +'%F %T')时间完成"

[root@node2 shell101]# date +‘%F %T’
2022-10-19 11:17:45

2. 变量

[root@node2 shell101]# A=hello
[root@node2 shell101]# echo $A
hello
[root@node2 shell101]# echo ${A}
hello
[root@node2 shell101]# echo $(A)
-bash: A: 未找到命令

[root@node2 shell101]# echo $(date +%F)
2022-10-19
[root@node2 shell101]# unset A
[root@node2 shell101]# echo $A

2.1 变量名规则:

  1. 区分大小写
[root@MissHou ~]# A=hello
[root@MissHou ~]# a=world
[root@MissHou ~]# echo $A
hello
[root@MissHou ~]# echo $a
world
  1. 变量名不能用特殊符号
[root@MissHou ~]# *A=hello
-bash: *A=hello: command not found
[root@MissHou ~]# ?A=hello
-bash: ?A=hello: command not found
[root@MissHou ~]# @A=hello
-bash: @A=hello: command not found

特别说明:对于有空格的字符串给变量赋值时,要用引号引起来
[root@MissHou ~]# A=hello world
-bash: world: command not found
[root@MissHou ~]# A="hello world"
[root@MissHou ~]# A='hello world'
  1. 变量名不能以数字开头
[root@MissHou ~]# 1A=hello
-bash: 1A=hello: command not found
[root@MissHou ~]# A1=hello
注意:不能以数字开头并不代表变量名中不能包含数字呦。
  1. 变量名两边不能有空格
[root@MissHou ~]# A =123
-bash: A: command not found
[root@MissHou ~]# A= 123
-bash: 123: command not found
[root@MissHou ~]# A = 123
-bash: A: command not found
[root@MissHou ~]# A=123
[root@MissHou ~]# echo $A
123

2.2 定义方式

㈠ 基本方式

直接赋值给一个变量

[root@MissHou ~]# A=1234567
[root@MissHou ~]# echo $A
1234567
[root@MissHou ~]# echo ${A:2:4}		表示从A变量中第3个字符开始截取,截取4个字符
3456

echo ${A:2} 从第三个开始截取,一直到截取到最后

说明:
$变量名 和 ${变量名}的异同
相同点:都可以调用变量
不同点:${变量名}可以只截取变量的一部分,而$变量名不可以

${}的方式可以切片
㈡ 命令执行结果赋值给变量

将命令的结果赋值给变量
[root@node2 shell101]# A=$(hostname)
[root@node2 shell101]# echo $A
node2

[root@MissHou ~]# B=`date +%F`
[root@MissHou ~]# echo $B
2019-04-16
[root@MissHou ~]# C=$(uname -r)
[root@MissHou ~]# echo $C
2.6.32-696.el6.x86_64

[root@node2 shell101]# cat /etc/redhat-release —查看系统版本
CentOS Linux release 7.5.1804 (Core)
[root@node2 shell101]# uname -r —查看内核版本
3.10.0-862.el7.x86_64

交互式定义变量(read)

**目的:**让用户自己给变量赋值,比较灵活。

语法:read [选项] 变量名

常见选项:

选项释义
-p定义提示用户的信息
-n定义字符数(限制变量值的长度)
-s不显示(不显示用户输入的内容)
-t定义超时时间,默认单位为秒(限制用户输入变量值的超时时间)

举例说明:

用法1:用户自己定义变量值
[root@MissHou ~]# read name
harry
[root@MissHou ~]# echo $name
harry
[root@MissHou ~]# read -p "Input your name:" name
Input your name:tom
[root@MissHou ~]# echo $name
tom


[root@node2 shell101]# read -p "password:" -s pwd
password: 输入,这里不显示密码
[root@node2 shell101]# echo $pwd
123

用法2:变量值来自文件

[root@MissHou ~]# cat 1.txt 
10.1.1.1 255.255.255.0

[root@MissHou ~]# read ip mask < 1.txt 
[root@MissHou ~]# echo $ip
10.1.1.1
[root@MissHou ~]# echo $mask
255.255.255.0
[root@node2 shell101]# vi my.config
[root@node2 shell101]# vi my.sh
[root@node2 shell101]# chmod +x my.sh
[root@node2 shell101]# ./my.sh 
ip: 10.0.218.25
mask: 255.255.0.1

my.config

10.0.218.25 255.255.0.1

my.sh

read ip mask < my.config
echo “ip:” $ip
echo “mask:” $mask

练习

[root@node2 shell101]# cat my.config 
ip=10.0.218.25
mask=255.255.0.1

[root@node2 shell101]# ip=$(grep ip my.config|cut -d= -f2)
[root@node2 shell101]# echo $ip
10.0.218.25

㈣ 定义有类型的变量(declare)

目的: 给变量做一些限制,固定变量的类型,比如:整型、只读

用法:declare 选项 变量名=变量值

常用选项:

选项释义举例
-i将变量看成整数declare -i A=123
-r定义只读变量declare -r B=hello
-a定义普通数组;查看普通数组
-A定义关联数组;查看关联数组
-x将变量通过环境导出declare -x AAA=123456 等于 export AAA=123456

举例说明:

[root@MissHou ~]# declare -i A=123
[root@MissHou ~]# echo $A
123
[root@MissHou ~]# A=hello
[root@MissHou ~]# echo $A
0

[root@MissHou ~]# declare -r B=hello
[root@MissHou ~]# echo $B
hello
[root@MissHou ~]# B=world
-bash: B: readonly variable
[root@MissHou ~]# unset B
-bash: unset: B: cannot unset: readonly variable

导出为环境变量

[root@node2 shell101]# env |grep 变量名
[root@node2 shell101]# AAA=yanweiling
[root@node2 shell101]# env|grep AAA
[root@node2 shell101]# export AAA
[root@node2 shell101]# env |grep AAA
AAA=yanweiling



[root@node2 shell101]# declare -x BBB=xinzhou
[root@node2 shell101]# env|grep BBB
BBB=xinzhou

2.3 变量的分类

㈠ 本地变量

  • 本地变量:当前用户自定义的变量。当前进程中有效,其他进程及当前进程的子进程无效。

设置本地变量A=hello以后
在这里插入图片描述
查看进程之间的父子关系 ps auxf |grep bash

练习

[root@node2 shell101]# A=1
[root@node2 shell101]# echo $A
1
[root@node2 shell101]# ps
  PID TTY          TIME CMD
 1857 pts/0    00:00:00 bash
16160 pts/0    00:00:00 ps    ----说明当前进程所在的bash是1857
[root@node2 shell101]# /bin/bash  进入到/bin/bash下
[root@node2 shell101]# ps
  PID TTY          TIME CMD
 1857 pts/0    00:00:00 bash
16247 pts/0    00:00:00 bash
16269 pts/0    00:00:00 ps   ---发现上层进程id是16247,再往上是1857
[root@node2 shell101]# ps -auxf |grep bash  ---查看进程的父子关系
root      1857  0.0  0.1 118136  2408 pts/0    Ss   10:16   0:00  |   \_ -bash
root     16247  0.0  0.1 117832  2132 pts/0    S    13:23   0:00  |   |   \_ /bin/bash
root     16692  0.0  0.0 114984  1012 pts/0    S+   13:23   0:00  |   |       \_ grep --color=auto bash
root      1867  0.0  0.1 117832  2100 pts/1    Ss   10:16   0:00  |   \_ -bash
root     16682  0.0  0.0 115340  1584 ?        Ss   13:23   0:00  |   \_ bash -c export LANG="en_US";export LANGUAGE="en_US";export LC_ALL="en_US";free;echo finalshell_separator;uptime;echo finalshell_separator;cat /proc/net/dev;echo finalshell_separator;df;echo finalshell_separator;sleep 1;free;echo finalshell_separator;uptime;echo finalshell_separator;cat /proc/net/dev;echo finalshell_separator;df;echo finalshell_separator;
[root@node2 shell101]# echo $A   --在子进程中查看变量,发现没有

[root@node2 shell101]# 
[root@node2 shell101]# exit  ---退出子进程
exit
[root@node2 shell101]# ps
  PID TTY          TIME CMD
 1857 pts/0    00:00:00 bash
19008 pts/0    00:00:00 ps
[root@node2 shell101]# echo $A
1

㈡ 环境变量
环境变量:当前进程有效,并且能够被子进程调用。

  • env查看当前用户的环境变量
  • set查询当前用户的所有变量(临时变量与环境变量)
  • export 变量名=变量值 或者 `变量名=变量值;export
[root@MissHou ~]# export A=hello		临时将一个本地变量(临时变量)变成环境变量
[root@MissHou ~]# env|grep ^A
A=hello

永久生效:
vim /etc/profile 或者 ~/.bashrc
export A=hello
或者
A=hello
export A

说明:系统中有一个变量PATH,环境变量
export PATH=/usr/local/mysql/bin:$PATH

㈢ 全局变量

  • 全局变量:全局所有的用户和程序都能调用,且继承,新建的用户也默认能调用.

  • 解读相关配置文件

文件名说明备注
$HOME/.bashrc当前用户的bash信息,用户登录时读取定义别名、umask、函数等
$HOME/.bash_profile当前用户的环境变量,用户登录时读取
$HOME/.bash_logout当前用户退出当前shell时最后读取定义用户退出时执行的程序等
/etc/bashrc全局的bash信息,所有用户都生效
/etc/profile全局环境变量信息系统和所有用户都生效
$HOME/.bash_history用户的历史命令history -w 保存历史记录 history -c 清空历史记录

**说明:**以上文件修改后,都需要重新source让其生效或者退出重新登录。

  • 用户登录系统读取相关文件的顺序
    1. /etc/profile
    2. $HOME/.bash_profile
    3. $HOME/.bashrc
    4. /etc/bashrc
    5. $HOME/.bash_logout

先读取环境变量,再去读取bash信息

在这里插入图片描述
/etc/profile 不要轻易动,如果要增加函数或者是别名,去/etc/bashrc中添加

在这里插入图片描述

全局环境变量,建议放到/etc/profile中

查看下 ~目录下,隐藏的文件

[root@node2 ~]# ls -a | grep '^\.'
.
..
.bash_history
.bash_logout
.bash_profile
.bashrc
.cshrc
.dbshell
.mongorc.js
.oracle_jre_usage
.rediscli_history
.ssh
.tcshrc

那当/etc/bashrc 和~/.bashrc中有相同别名,以哪个为准呢?
我们来看下~/.bashrc内容

[root@node2 ~]# cat ~/.bashrc 
# .bashrc

export JAVA_HOME=/usr/java/latest
export ZOOKEEPER_HOME=/usr/local/zk
export SCALA_HOME=/usr/local/scala
export STORM_HOME=/usr/local/storm
export PATH=$PATH:$JAVA_HOME/bin:$ZOOKEEPER_HOME/bin:$SCALA_HOME/bin:$STORM_HOME/bin

# User specific aliases and functions

alias rm='rm -i'
alias cp='cp -i'
alias mv='mv -i'

# Source global definitions
if [ -f /etc/bashrc ]; then   
        . /etc/bashrc
fi

这句话的意思是,如果发现有某个别名在/etc/bashrc中也存在的话,则 执行
. /etc/bashrc ,等同于source /etc/bashrc,就会执行下全局的bashrc文件

所以,如果别名是放在这段代码前面,则以/etc/bashrc中的别名为准;
如果别名放在这段代码以后,则以~/.bashrc中的别名为准

系统变量

系统变量(内置bash中变量) : shell本身已经固定好了它的名字和作用.

内置变量含义
$?上一条命令执行后返回的状态;状态值为0表示执行正常,非0表示执行异常或错误
$0当前执行的程序或脚本名
$#脚本后面接的参数的个数
$*脚本后面所有参数,参数当成一个整体输出,每一个变量参数之间以空格隔开
$@脚本后面所有参数,参数是独立的,也是全部输出
$1~$9脚本后面的位置参数,$1表示第1个位置参数,依次类推
${10}~${n}扩展位置参数,第10个位置变量必须用{}大括号括起来(2位数字以上扩起来)
$$当前所在进程的进程号,如echo $$
$!后台运行的最后一个进程号 (当前终端)
!$调用最后一条命令历史中的参数

$*:表示将变量看成一个整体
$@:表示变量是独立的

练习
查看上一条命令执行是否ok

[root@node2 ~]# ls
anaconda-ks.cfg  perl-5.16.1.tar.gz  redis-3.2.8.tar.gz  tcl8.6.1-src.tar.gz
perl-5.16.1      redis-3.2.8         tcl8.6.1            zookeeper.out
[root@node2 ~]# echo $?
0
[root@node2 ~]# l
-bash: l: 未找到命令
[root@node2 ~]# echo $?
127     ----非零,则表示失败

vi my.sh
#!/bin/env bash
echo "执行的脚本是:" $0
echo "执行的参数有$#个,参数是:$*"


[root@node2 shell101]# ./my.sh param1 param2
执行的脚本是: ./my.sh
执行的参数有2个,参数是:param1 param2

[root@node2 shell101]# echo $0
-bash
[root@node2 shell101]# echo $$   查看当前进程号
1857
[root@node2 shell101]# ps
  PID TTY          TIME CMD
 1857 pts/0    00:00:00 bash
 2842 pts/0    00:00:00 ps

vi variable.sh
#!/bin/env bash
#Name:variable.sh
#了解shell内置变量中的位置参数含义
echo "\$0 = $0"
echo "\$# = $#"
echo "\$* = $*"
echo "\$@ = $@"
echo "\$1 = $1"
echo "\$2 = $2"
echo "\$3 = $3"
echo "\$11 = ${11}"
echo "\$12 = ${12}"

chmod +x variable.sh

[root@node2 shell101]# ./variable.sh 1 2 3 4 5 6 7 8 9 10 11 12
$0 = ./variable.sh
$# = 12
$* = 1 2 3 4 5 6 7 8 9 10 11 12
$@ = 1 2 3 4 5 6 7 8 9 10 11 12
$1 = 1
$2 = 2
$3 = 3
$11 = 11
$12 = 12

$* 和 $@的区别

vi 3.sh
#!/bin/bash
for i in "$@"
do
echo $i
done

echo "======我是分割线======="

for i in "$*"
do
echo $i
done

[root@MissHou ~]# bash 3.sh a b c
a
b
c
======我是分割线=======
a b c

查看后台运行的进程 jobs

jobs命令显示了当前shell环境中已启动的作业状态。

& 将命令放在后台运行

[root@node2 shell101]# jobs     --查看作业状态
[root@node2 shell101]# sleep 500 &  睡500s,放在后台运行
[1] 19836
[root@node2 shell101]# jobs   --查看一下
[1]+  运行中                  sleep 500 &
[root@node2 shell101]# sleep 600  睡600s,前台运行
^C    ---按下ctrl+c
[root@node2 shell101]# jobs
[1]+  运行中                  sleep 500 &
[root@node2 shell101]# sleep 600 
^Z   --按下ctrl+z
[2]+  已停止                  sleep 600
[root@node2 shell101]# jobs
[1]-  运行中                  sleep 500 &
[2]+  已停止                  sleep 600
[root@node2 shell101]# 


[root@node2 shell101]# ps -ef |grep sleep   --查看下进程号
用户      进程号  父进程
root     19836  1857  0 16:20 pts/0    00:00:00 sleep 500
root     20122  1857  0 16:20 pts/0

[root@node2 shell101]# echo $!     ----查询最后一个进程号
19836

扩展

ctrl+c和ctrl+z都是中断命令,但是他们的作用却不一样.
ctrl+c是强制中断程序的执行,
而ctrl+z的是将任务中断,但是此任务并没有结束,他仍然在进程中他只是维持挂起的状态,用户可以使用fg/bg操作继续前台或后台的任务,fg命令重新启动前台被中断的任务,bg命令把被中断的任务放在后台执行.
例如:
当你vi一个文件是,如果需要用shell执行别的操作,但是你又不打算关闭vi,因为你得
存盘推出,你可以简单的按下ctrl+z,shell会将vi进程挂起~,当你结束了那个shell操作之后,你可以用fg命令继续vi你的文件.

查询最后一条命令的参数

[root@node2 shell101]# ls -l
总用量 16
-rwxr-xr-x. 1 root root 119 1019 11:16 first.sh
-rw-r--r--. 1 root root  32 1019 12:49 my.config
-rwxr-xr-x. 1 root root 104 1019 16:03 my.sh
-rwxr-xr-x. 1 root root 227 1019 16:10 variable.sh
[root@node2 shell101]# echo !$
echo -l
-l

3. 简单的四则运算

算术运算:默认情况下,shell就只能支持简单的整数运算

运算内容:加(+)、减(-)、乘(*)、除(/)、求余数(%)

  1. 四则运算符号
表达式举例
$(( ))echo $((1+1))
$[ ]echo $[10-5]
exprexpr 10 / 5
letn=1;let n+=1 等价于 let n=n+1
[root@node2 shell101]# echo $((5*5))
25
[root@node2 shell101]# echo $[10/6]
1

[root@node2 shell101]# expr 1 + 1   -----注意expr 用法,要注意空格
2
[root@node2 shell101]# expr 1 *  5
expr: 语法错误
[root@node2 shell101]# expr 1 * 5
expr: 语法错误
[root@node2 shell101]# expr 1 \* 5   ---乘法要转义一下
5
[root@node2 shell101]# expr 10 / 5
2
[root@node2 shell101]# expr 10 % 5
0
[root@node2 shell101]# 

let练习

[root@node2 shell101]# n=1;let n = n+1;echo $n
-bash: let: =: 语法错误: 期待操作数 (错误符号是 "="1    ----注意等号左右不要有空格
[root@node2 shell101]# n=1;let n=n+1;echo $n
2
[root@node2 shell101]# let n+=2
[root@node2 shell101]# echo $n
4

[root@node2 shell101]# n=1;n=$((n+1));echo $n
2
[root@node2 shell101]# let n=n**3   ---计算3次方
[root@node2 shell101]# echo $n
8
[root@node2 shell101]# let n/=2;echo $n
4


计算非整数 ,需要用到bc程序
centos7上安装bc

yum -y install bc

[root@node2 shell101]# echo 1+1.5
1+1.5
[root@node2 shell101]# echo 1+1.5|bc
2.5
[root@node2 shell101]# echo $[1+1.5]
-bash: 1+1.5: 语法错误: 无效的算术运算符 (错误符号是 ".5"[root@node2 shell101]# echo $[1+1.5|bc]
-bash: 1+1.5|bc: 语法错误: 无效的算术运算符 (错误符号是 ".5|bc"[root@node2 shell101]# echo $[1+1.5]|bc
-bash: 1+1.5: 语法错误: 无效的算术运算符 (错误符号是 ".5"[root@node2 shell101]# echo ((1+1.5))
-bash: 未预期的符号 `(' 附近有语法错误
[root@node2 shell101]# echo ((1+1.5))|bc
-bash: 未预期的符号 `(' 附近有语法错误
[root@node2 shell101]# echo ((1+1.5|bc))
-bash: 未预期的符号 `(' 附近有语法错误
[root@node2 shell101]# 

计算次方,可以用$(()) , $[], let 来实现,expr 无法实现

2.了解i++和++i

对变量的值的影响

[root@MissHou ~]# i=1
[root@MissHou ~]# let i++
[root@MissHou ~]# echo $i
2
[root@MissHou ~]# j=1
[root@MissHou ~]# let ++j
[root@MissHou ~]# echo $j
2

表达式的值的影响

[root@MissHou ~]# unset i j
[root@MissHou ~]# i=1;j=1
[root@MissHou ~]# let x=i++         先赋值,再运算
[root@MissHou ~]# let y=++j         先运算,再赋值
[root@MissHou ~]# echo $i
2
[root@MissHou ~]# echo $j
2
[root@MissHou ~]# echo $x
1
[root@MissHou ~]# echo $y
2

3.1 了解 ++i 和i++

[root@MissHou ~]# unset i j
[root@MissHou ~]# i=1;j=1
[root@MissHou ~]# let x=i++         先赋值,再运算
[root@MissHou ~]# let y=++j         先运算,再赋值
[root@MissHou ~]# echo $i
2
[root@MissHou ~]# echo $j
2
[root@MissHou ~]# echo $x
1
[root@MissHou ~]# echo $y
2

4. 四、扩展补充

1. 数组定义

㈠ 数组分类

  • 普通数组:只能使用整数作为数组索引(元素的下标)
  • 关联数组:可以使用字符串作为数组索引(元素的下标)

㈡ 普通数组定义

一次赋予一个值

数组名[索引下标]=值
array[0]=v1
array[1]=v2
array[2]=v3
array[3]=v4

[root@node2 yunwei]# array[0]=harray
[root@node2 yunwei]# array[1]=jack
[root@node2 yunwei]# array[3]=tom
[root@node2 yunwei]# echo ${array[*]}
harray jack tom
[root@node2 yunwei]# echo ${array[3]}
tom
[root@node2 yunwei]# echo ${array[2]}

[root@node2 yunwei]# echo ${#array[*]}
3

一次赋予多个值

数组名=(值1 值2 值3 ...)
array=(var1 var2 var3 var4)

array1=(`cat /etc/passwd`)			将文件中每一行赋值给array1数组
array2=(`ls /root`)
array3=(harry amy jack "Miss Hou")
array4=(1 2 3 4 "hello world" [10]=linux)

㈢ 数组的读取

${数组名[元素下标]}

echo ${array[0]}			获取数组里第一个元素
echo ${array[*]}			获取数组里的所有元素
echo ${#array[*]}			获取数组里所有元素个数
echo ${!array[@]}    	获取数组元素的索引下标
echo ${array[@]:1:2}    访问指定的元素;1代表从下标为1的元素开始获取;2代表获取后面几个元素

查看普通数组信息:
[root@MissHou ~]# declare -a

练习

[root@node2 yunwei]# array=(var1 var2 var3 var4)
[root@node2 yunwei]# array1=(`head /etc/passwd`)
[root@node2 yunwei]# array2=(`ls /root`)
[root@node2 yunwei]# array3=(1 2 3 4 "hello" [10]=linux)
declare -a

[root@node2 yunwei]# declare -a
declare -a BASH_ARGC='()'
declare -a BASH_ARGV='()'
declare -a BASH_LINENO='()'
declare -a BASH_SOURCE='()'
declare -ar BASH_VERSINFO='([0]="4" [1]="2" [2]="46" [3]="2" [4]="release" [5]="x86_64-redhat-linux-gnu")'
declare -a DIRSTACK='()'
declare -a FUNCNAME='()'
declare -a GROUPS='()'
declare -a PIPESTATUS='([0]="0")'
declare -a array='([0]="var1" [1]="var2" [2]="var3" [3]="var4")'
declare -a array1='([0]="root:x:0:0:root:/root:/bin/bash" [1]="bin:x:1:1:bin:/bin:/sbin/nologin" [2]="daemon:x:2:2:daemon:/sbin:/sbin/nologin" [3]="adm:x:3:4:adm:/var/adm:/sbin/nologin" [4]="lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin" [5]="sync:x:5:0:sync:/sbin:/bin/sync" [6]="shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown" [7]="halt:x:7:0:halt:/sbin:/sbin/halt" [8]="mail:x:8:12:mail:/var/spool/mail:/sbin/nologin" [9]="operator:x:11:0:operator:/root:/sbin/nologin")'
declare -a array2='([0]="anaconda-ks.cfg" [1]="dead.letter" [2]="perl-5.16.1" [3]="perl-5.16.1.tar.gz" [4]="redis-3.2.8" [5]="redis-3.2.8.tar.gz" [6]="tcl8.6.1" [7]="tcl8.6.1-src.tar.gz" [8]="zookeeper.out")'
declare -a array3='([0]="1" [1]="2" [2]="3" [3]="4" [4]="hello" [10]="linux")'
[root@node2 yunwei]# 
[root@node2 yunwei]# declare -a |grep array4  --过滤看下array4
declare -a array4='([0]="1" [2]="2" [9]="9")'
[root@node2 yunwei]# declare -a myarray=(1 2 3 4 5 ) 
---我们也可以采用delcare -a 数组名=()的方式进行声明一个数组
[root@node2 yunwei]# echo ${myarray[*]}
1 2 3 4 5
[root@node2 yunwei]# 

扩展

安装vim yum -y install vim
vim 编辑文档,文档内容是带有颜色的,例如vim /etc/passwd 进入文档以后:set nu将显示行号
在这里插入图片描述

㈣ 关联数组定义

①首先声明关联数组

declare -A asso_array1

declare -A asso_array1
declare -A asso_array2
declare -A asso_array3

普通数组中下标只能是数值,而关联数组的下标可以是名称,有点像java的HashMap类型

[root@node2 yunwei]# declare -A a_array1
[root@node2 yunwei]# declare -A a_array2
[root@node2 yunwei]# declare -A a_array3
[root@node2 yunwei]# declare -A   --查询关联数组
declare -A BASH_ALIASES='()'
declare -A BASH_CMDS='()'
declare -A a_array1='()'
declare -A a_array2='()'
declare -A a_array3='()'
[root@node2 yunwei]# declare -a |grep ^a_   ---普通数组中没有


-----------赋值计算------------------------------
[root@node2 yunwei]# a_array1[linux]=one
[root@node2 yunwei]# a_array1[java]=two
[root@node2 yunwei]# a_array1[php]=three
[root@node2 yunwei]# declare -A
declare -A BASH_ALIASES='()'
declare -A BASH_CMDS='()'
declare -A a_array1='([php]="three" [java]="two" [linux]="one" )'
declare -A a_array2='()'
declare -A a_array3='()'

[root@node2 yunwei]# echo ${a_array1[*]}  ---关联数组是无序的
three two one

[root@node2 yunwei]# 


[root@node2 yunwei]# a_array2=([name1]=harray [name2]=jack [name3]=amy [name4]="Miss Hou")
[root@node2 yunwei]# declare -A |grep a_array2
declare -A a_array2='([name3]="amy" [name2]="jack" [name1]="harray" [name4]="Miss Hou" )'
[root@node2 yunwei]# 


练习

[root@node2 yunwei]# declare -A a_array
[root@node2 yunwei]# a_array[php]=8
[root@node2 yunwei]# a_array[linux]=3
[root@node2 yunwei]# a_array[java]=7
[root@node2 yunwei]# a_array[python]=10
[root@node2 yunwei]# declare -A |grep -w a_array
declare -A a_array='([php]="8" [java]="7" [linux]="3" [python]="10" )'
[root@node2 yunwei]# echo ${a_array[*]}
8 7 3 10
[root@node2 yunwei]# echo ${!a_array[*]}
php java linux python
[root@node2 yunwei]# 
② 数组赋值

一次赋一个值

数组名[索引or下标]=变量值
# asso_array1[linux]=one
# asso_array1[java]=two
# asso_array1[php]=three

一次赋多个值

# asso_array2=([name1]=harry [name2]=jack [name3]=amy [name4]="Miss Hou")

查看关联数组

# declare -A
declare -A asso_array1='([php]="three" [java]="two" [linux]="one" )'
declare -A asso_array2='([name3]="amy" [name2]="jack" [name1]="harry" [name4]="Miss Hou" )'

获取关联数组值

# echo ${asso_array1[linux]}
one
# echo ${asso_array1[php]}
three
# echo ${asso_array1[*]}
three two one
# echo ${!asso_array1[*]}
php java linux
# echo ${#asso_array1[*]}
3
# echo ${#asso_array2[*]}
4
# echo ${!asso_array2[*]}
name3 name2 name1 name4

其他定义方式

[root@MissHou shell05]# declare -A books
[root@MissHou shell05]# let books[linux]++
[root@MissHou shell05]# declare -A|grep books
declare -A books='([linux]="1" )'
[root@MissHou shell05]# let books[linux]++
[root@MissHou shell05]# declare -A|grep books
declare -A books='([linux]="2" )'
③ 数组的拼接

首先声明关联数组
数组的拼接:可以使用@和*获取数组的所有元素后拼接成一个新的数组

语法

arr_name=(${arr1[@]} ${arr2[@]})

arr_name=(${arr1[]} ${arr2[]})

④ 数组的删除

数组的删除

删除数组指定索引的元素 unset arr_name[n]
删除数组 unset arr_name
关联数组通过unset arr_name[key]的方式删除指定元素

2. 其他变量定义

取出一个目录下的目录和文件:dirnamebasename

# A=/root/Desktop/shell/mem.txt 
# echo $A
/root/Desktop/shell/mem.txt
# dirname $A   取出目录
/root/Desktop/shell
# basename $A  取出文件
mem.txt

变量"内容"的删除和替换

一个“%”代表从右往左删除
两个“%%”代表从右往左去掉最多
一个“#”代表从左往右去掉删除
两个“##”代表从左往右去掉最多

举例说明:
# url=www.taobao.com
# echo ${#url}		     获取变量的长度
# echo ${url#*.}
# echo ${url##*.}
# echo ${url%.*}
# echo ${url%%.*}

实操

[root@node2 yunwei]# url=www.taobao.com
[root@node2 yunwei]# echo ${#url}
14
[root@node2 yunwei]# echo ${url#*.}
taobao.com
[root@node2 yunwei]# echo ${url#*.*.}
com
[root@node2 yunwei]# echo ${url##*.*.}
com
[root@node2 yunwei]# echo ${url##}
www.taobao.com
[root@node2 yunwei]# echo ${url##*.}
com
[root@node2 yunwei]# echo ${url%.*}
www.taobao
[root@node2 yunwei]# echo ${url%%.*}
www
[root@node2 yunwei]# 

替换:/ 和 //
 1015  echo ${url/ao/AO}  用AO代替ao(从左往右第一个)
 1017  echo ${url//ao/AO}   贪婪替换(替代所有)
 
替代: - 和 :-  +和:+
 1019  echo ${abc-123}
 1020  abc=hello
 1021  echo ${abc-444}
 1022  echo $abc
 1024  abc=
 1025  echo ${abc-222}

${变量名-新的变量值} 或者 ${变量名=新的变量值}
变量没有被赋值:会使用“新的变量值“ 替代
变量有被赋值(包括空值): 不会被替代

 1062  echo ${ABC:-123}
 1063  ABC=HELLO
 1064  echo ${ABC:-123}
 1065  ABC=
 1066  echo ${ABC:-123}

${变量名:-新的变量值} 或者 ${变量名:=新的变量值}
变量没有被赋值或者赋空值:会使用“新的变量值“ 替代
变量有被赋值: 不会被替代

 1116  echo ${abc=123}
 1118  echo ${abc:=123}

[root@MissHou ~]# unset abc
[root@MissHou ~]# echo ${abc:+123}

[root@MissHou ~]# abc=hello
[root@MissHou ~]# echo ${abc:+123}
123
[root@MissHou ~]# abc=
[root@MissHou ~]# echo ${abc:+123}

${变量名+新的变量值}
变量没有被赋值或者赋空值:不会使用“新的变量值“ 替代
变量有被赋值: 会被替代
[root@MissHou ~]# unset abc
[root@MissHou ~]# echo ${abc+123}

[root@MissHou ~]# abc=hello
[root@MissHou ~]# echo ${abc+123}
123
[root@MissHou ~]# abc=
[root@MissHou ~]# echo ${abc+123}
123
${变量名:+新的变量值}
变量没有被赋值:不会使用“新的变量值“ 替代
变量有被赋值(包括空值): 会被替代

[root@MissHou ~]# unset abc
[root@MissHou ~]# echo ${abc?123}
-bash: abc: 123

[root@MissHou ~]# abc=hello
[root@MissHou ~]# echo ${abc?123}
hello
[root@MissHou ~]# abc=
[root@MissHou ~]# echo ${abc?123}

${变量名?新的变量值}
变量没有被赋值:提示错误信息
变量被赋值(包括空值):不会使用“新的变量值“ 替代

[root@MissHou ~]# unset abc
[root@MissHou ~]# echo ${abc:?123}
-bash: abc: 123
[root@MissHou ~]# abc=hello
[root@MissHou ~]# echo ${abc:?123}
hello
[root@MissHou ~]# abc=
[root@MissHou ~]# echo ${abc:?123}
-bash: abc: 123

${变量名:?新的变量值}
变量没有被赋值或者赋空值时:提示错误信息
变量被赋值:不会使用“新的变量值“ 替代

说明:?主要是当变量没有赋值提示错误信息的,没有赋值功能
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值