Linux系列shell编程之变量

网友投稿 612 2022-05-29

1、shell的介绍

Shell 本身是一个用c语言编写的程序,它是用户使用Unix/linux的桥梁,用户的大部分工作都是通过Shell完成的。

Shell 既是一种命令语言,又是一种程序设计语言:作为命令语言,它交互式地解释和执行用户输入的命令;作为程序设计语言,它定义了各种变量和参数,并提供了许多在高级语言中才具有的控制结构,包括循环和分支。

Shell 它虽然不是Unix/Linux系统内核的一部分,但它调用了系统核心的大部分功能来执行程序、建立文件并以并行的方式协调各个程序的运行。Shell 是用户与内核进行交互操作的一种接口,目前最流行的Shell称为bash Shell(Bourne Again Shell)。

Shell是一门编程语言(解释型的编程语言,即shell脚本(就是在用linux的shell命令编程),Shell 脚本程序从脚本中一行一行读取并执行这些命令,相当于一个用户把脚本中的命令一行一行敲到Shell提示符下执行。

Shell是一种脚本语言,那么,就必须有解释器来执行这些脚本。Unix/Linux上常见的shell脚本解释器有bash、sh、csh、ksh等,习惯上把它们称作一种Shell。

我们常说有多少种Shell,其实说的是Shell脚本解释器,可以通过cat /etc/shells命令查看系统中安装的shell,不同的shell可能支持的命令语法是不相同的。

sh是Unix标准默认的shell,由Steve Bourne 开发,是Bourne Shell的缩写。

bash是Linux标准默认的shell,由Brian Fox 和Chet Ramey共同完成,是Bourne Again Shell的缩写。

shell本身支持的命令并不多,内部命令一共有40个,但是它可以调用其他的程序,每个程序就是一个命令,这使得Shell命令的数量可以无限扩展,其结果就是Shell的功能非常强大,完全能够胜任Linux的日常管理工作,如文本或字符串检索、文件的查找或创建、大规模软件的自动部署、更改系统设置、监控服务器性能、发送报警邮件、抓取网页内容、压缩文件等。

# 查看系统中安装的shell [hadoop@image_boundary ~]$ cat /etc/shells /bin/sh /bin/bash /sbin/nologin /bin/dash

2、shell语言

shell脚本代码通常写在普通文本文件中,通常以.sh结尾,虽然不是强制要求,但希望大家最好这么做。

// vim是创建并打开了一个文件。 // a.sh存在,就是打开该文件; // a.sh不存在,就是创建该文件。 [root@image_boundary ~]# vim a.sh

上述命令:创建并打开了a.sh这个文件。

我们在该脚本中写入如下两行代码。

// 一般在一个shell脚本的首行需要输入【#!/bin/bash】这句代码。 // 【#!/bin/bash】表示设置默认解释器类型。 // 但是如果【指定解释器执行】该脚本时,该行无效。 #!/bin/bash echo "Hello World"

操作如下:

Linux系列:shell编程之变量

[root@image_boundary ~]# sh a.sh Hello World [root@image_boundary ~]# bash a.sh Hello World

操作如下:

[root@bigdata111 ~]# source a.sh aa [root@bigdata111 ~]# . a.sh aa

注意1:source命令也称为“点命令”也就是一个点符号(.),是bash的内部命令。

注意2:source命令通常用于重新执行刚修改的初始化文件,使之立即生效,而不必注销并重新登录。

注意3:.和脚本名称之间是有空格的。

# 1 先确保该shell脚本文件有执权限 # chmod命令可以修改可读、可写、可执行的权限 chmod # 2 相对路径执行法(每次执行,必须切换到文件所在目录) # 这里的点(.)指的是“当前路径”。 ./脚本文件名 # 3 绝对路径执行法(只要有权限,什么路径下都可以执行) /root/脚本文件名

操作如下:

// 修改该文件的权限,使其具有可执行的权限。 [root@image_boundary ~]# chmod 744 a.sh [root@image_boundary ~]# ll total 4 -rwxr--r--. 1 root root 31 Oct 18 09:18 a.sh // 相对路径执行:必须切换到该文件的目录当中去,才可以执行。 [root@image_boundary ~]# ./a.sh Hello World // 绝对路径执行:在任何地方都可以执行。 [root@image_boundary ~]# /root/a.sh Hello World

3、变量

// set:查看所有系统变量 [root@image_boundary ~]# set // 常用的系统变量:$PWD $PATH $SHELL $USER $HOME

系统变量可以通过set命令查看,用户环境变量可以通过env查看。

// echo $PATH :查看Linux中配置过的环境变量 [root@image_boundary ~]# echo $PATH /usr/local/tomcat/apache-tomcat-8.5.45/bin:/usr/local/java/jdk1.8.0_73/bin:/usr/lib64/qt-3.3/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin // echo $PWD :显示当前位置的绝对路径 [root@image_boundary ~]# echo $PWD /root // echo $USER : 显示当前你是哪一个用户登陆的虚拟机 [root@image_boundary ~]# echo $USER root [huangwei@image_boundary root]$ echo $USER huangwei // echo $HOME : 显示用户的家目录 [root@image_boundary ~]# echo $HOME /root [huangwei@image_boundary root]$ echo $HOME /home/huangwei // echo $SHELL : 显示linux系统默认的shell [root@image_boundary ~]# echo $SHELL /bin/bash

语法格式:变量名=值 注意1:在shell脚本中定义变量,等号两侧,绝对不能有空格; 注意2:值中有空格,需要使用引号; 注意3:单引号会内容脱意,双引号可以识别变量; 注意4:变量紧挨着其它单词,可以使用${A}来获取变量A的值;

// shell中定义变量,等号两侧绝对不能有空格; [root@bigdata111 ~]# A = 12 bash: A: command not found [root@bigdata111 ~]# A=12 // 使用$号,可以获取变量的值; [root@bigdata111 ~]# echo $A 12 [root@bigdata111 ~]# A=abc [root@bigdata111 ~]# echo $A abc [root@bigdata111 ~]# A="abc" [root@bigdata111 ~]# echo $A abc // 值中用空格,值需要使用引号引起来; [root@bigdata111 ~]# A=ab c -bash: c: command not found [root@bigdata111 ~]# A="ab c" [root@bigdata111 ~]# echo $A ab c

[root@bigdata111 ~]# A="Chen Li" [root@bigdata111 ~]# B='I love $A' // 单引号会导致内容脱意,双引号可以识别变量; [root@bigdata111 ~]# echo $B I love $A [root@bigdata111 ~]# B="I love $A" [root@bigdata111 ~]# echo $B I love Chen Li

// 变量紧挨其它单词,会导致$C无法正常取值; [root@bigdata111 ~]# C="dog" [root@bigdata111 ~]# D="Those are $Cs" [root@bigdata111 ~]# echo $D This are // 想要变量与其它单词区分,可以使用${C}; [root@bigdata111 ~]# D="Those are ${C}s" [root@bigdata111 ~]# echo $D Those are dogs // 注意以下几种写法的不同点; [root@image_boundary ~]# A="Dog" // a放在$A前面:a$A [root@image_boundary ~]# B="Those are a$A" // a放在$A后面:$Aa; [root@image_boundary ~]# C="Those are $Aa" [root@image_boundary ~]# echo $B Those are aDog [root@image_boundary ~]# echo $C Those are

1)撤销变量:unset 变量名; 2)设置只读变量:readonly 变量名=值; 注意:设置只读变量后,修改、撤销只读变量,会报错。

[root@image_boundary ~]# A=12 [root@image_boundary ~]# echo $A 12 // 撤销变量后,变量输出为空; [root@image_boundary ~]# unset A [root@image_boundary ~]# echo $A [root@image_boundary ~]#

[root@image_boundary ~]# readonly A=100 // 修改只读变量,会报错; [root@image_boundary ~]# A=666 -bash: A: readonly variable // 撤销只读变量,会报错; [root@image_boundary ~]# unset A -bash: unset: A: cannot unset: readonly variable

4、案例:变量的使用(有点意思的一个案例)

写两个脚本,在a.sh中调用b.sh执行,那我们想知道a脚本能不能获取到b脚本的变量,同时b脚本能不能获取到a脚本的变量?

// 脚本a.sh中的内容; #!/bin/bash A="A in a.sh" echo $A echo $B /root/b. sh // 脚本b.sh中的内容; #!/bin/bash B="B in b. sh" echo $B echo $A

使用cat命令分别查看这两个脚本文件中的内容。

[root@bigdata111 ~]# chmod 755 a.sh [root@bigdata111 ~]# chmod 755 b.sh

可以看到,a.sh和b.sh都有了可执行权限。

[root@bigdata111 ~]# sh a.sh

结果如下:

分析: 为什么a.sh中【echo $B】没有执行,b.sh中【echo $A】没有执行?

shell是一个脚本程序,对于脚本程序,都是从脚本中一行一行读取并执行这些命令。因此,第一个【echo $B】没有执行,显示为空。第二个b.sh中【echo $A】为 什么也为空,分析如图所示。

把A、B两个变量提升为全局变量!会出现什么结果呢?

注意:上图中,假如把A和B同时提升为“全局变量”,但是子进程b.sh可以使用父进程中的A变量,而父进程a.sh却不能使用子进程的B变量。

因此在a.sh中可以使用b.sh中的变量B;在b.sh中可以使用a.sh中的变量A。

为了更好地说明上述区别,我们在脚本中分别打印$$,显示进程数。

// $$:显示进程数 [root@image_boundary ~]# echo $$ 9544

第一种情况,使用“绝对路径调用方式”:

第二种情况,使用“内部命令调用方式”:

总结如下:

5、变量中几个常用符号

反引号``:键盘上Tab键上方的一个键,和~在一个格子上。

操作如下:

[root@bigdata111 ~]# A=`date` [root@bigdata111 ~]# echo $A Mon Sep 30 06:20:02 CST 2019 // $(变量):表示先计算,再赋值; [root@bigdata111 ~]# B=$(date) [root@bigdata111 ~]# echo $B Mon Sep 30 06:20:36 CST 2019 // 练习:你可以尝试以下以下操作,看看结果是什么? [root@bigdata111 ~]# ll total 8 -rw-r--r--. 1 root root 390 Oct 2 01:04 a.txt -rw-r--r--. 1 root root 0 Oct 2 01:03 b.txt drwxr-xr-x. 2 root root 4096 Oct 2 01:04 study [root@bigdata111 ~]# echo `ll` // 这个结果是什么 [root@bigdata111 ~]# echo $(ll) // 这个结果是什么

${var}:获取变量本来的值;变量存在,输出原有值;变量不存在,输出空。 ${var:-word}:判断某个变量是否存在。 变量存在且有值,输出变量var的值; 变量不存在,输出word。 ${var:+word}:判断某个变量是否存在。 变量存在且有值,输出word; 变量不存在,输出为空。 ${var:=word}:变量存在,返回变量var的值; 变量不存在,相当于创建一个新变量var,并赋值为word。 ${var:?message}:变量存在,输出变量var的值; 变量不存在,报错误。

// 0代表上一次正确执行,正数代表上一次未正确执行; $?表示上一个命令退出的状态码; $$ 表示当前进程编号; $0 表示当前脚本名称; $n 表示n位置的输入参数(n代表数字,n>=1); $# 表示获取参数的个数,常用于循环; $*和$@都表示获取参数列表。

操作如下:

[root@bigdata111 ~]# vim uni_var.sh [root@bigdata111 ~]# cat uni_var.sh #!/bin/bash echo $? #表示上一个命令退出的状态码 echo $$ #表示当前的进程编号 echo $0 #表示当前的脚本名称 echo $1 #表示第1个位置参数 echo $2 #表示第2个位置参数 echo $3 #表示第3个位置参数 echo $# #表示参数的个数 echo $@ #输出参数列表 echo $* #输出参数列表 [root@bigdata111 ~]# sh uni_var.sh aa bb cc 0 4192 uni_var.sh aa bb cc 3 aa bb cc aa bb cc

$*和$@都表示输出参数列表,区别如下:

操作如下:

结果如下:

Linux Shell

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:【python版QT学习】pyQT5上位机实战笔记
下一篇:华为云GaussDB专家走进课堂,跟莘莘学子聊聊数据库
相关文章