shell? 变量!

目录

​编辑

什么是shell

编译型语言和解释型语言 

解释型语言

变量 

1.局部变量:

2.环境变量通常又称“全局变量”

3.设置环境变量: 

命名法则举例

变量命名

取消变量

特殊变量

1、只读变量(常量):

查看常量值

括号的使用

位置变量

$* 和 $@ 的区别。

$0 引用名称的使用

shift命令: 整体往左移位

退出状态


shell? 变量!_第1张图片

 

什么是shell

shell 是一个命令解释器,提供用户和机器之间的交互
支持特定语法,比如逻辑判断、循环
每个用户都可以有自己特定的 shell
还有其他 zsh ksh
CentOS7 默认的 shell bash(Bourne Agin Shell)
Shell 是一个用 C 语言编写的程序,它是用户使用 Linux 的桥梁。 Shell 既是一种命令语言,又是一种程序设计语言。
Shell 是指一种应用程序,这个应用程序提供了一个界面,用户通过这个界面访问操作系统内核的服务。
shell 是一种解释型语言,这种语言经过编写后不经过任何编译就可以执行,是一种脚本语言。和编译型语言是执行前翻译不同,解释型语言的程序是执行时翻译,所以效率要差一些

编译型语言和解释型语言 

优点:
编译器一般会有预编译的过程对代码进行优化。因为编译只做一次,运行时不需要编译,所以编译型语言的程序执行效率高。可以脱离语言环境独立运行。
缺点:
编译之后如果需要修改就需要整个模块重新编译。编译的时候根据对应的运行环境生成机器码,不同的操作系统之间移植就会有问题,需要根据运行的操作系统环境编译不同的可执行文件。

 代表语言:

CC++PascalObject-Cswift等。

CentOS 系统中支持很多 shell, 可以通过查看 /etc/shells 文件,查看所支持的shell,目前大多数的 Linux 基本都使用 bash
[root@localhost ~]# cat /etc/shells 
/bin/sh
/bin/bash
/usr/bin/sh
/usr/bin/bash
/bin/tcsh
/bin/csh
[root@localhost ~]# 

解释型语言

解释性语言的程序不需要编译,相比编译型语言省了道工序,解释性语言在运行程序的时候才逐行翻译。每一个语句都是执行的时候才能翻译。这样解释性语言每执行一次要翻译一次,效率表较低
优点:
有良好的平台兼容性,在任何环境中都可以运行,前提是安装了解释器(虚拟机)。灵活,修改代码的时候直接修改就可以,可以快速部署,不用停机维护

缺点: 

每次运行的时候都要解释一遍,性能上不如编译型语言

代表语言:

JavaScriptPythonErlangPHPPerlRuby 

bash shell 有两种工作
[root@localhost shell]# cat kang.sh 
#!/bin/bash                        //是一个标记,告诉系统执行这个文件需要的解释器
#this line is a comment            // “#”号开头的行代表注释
echo "Hello world"
模式:互动模式和脚本模式。脚本模式效率更高,可以实现自动化

1.运行脚本有两种方法

使用bash命令执行

[root@localhost shell]# bash kang.sh 
Hello world

// “.”命令也都可以执行脚本,且不需要可执行权限

[root@localhost shell]# . kang.sh 
Hello world

2. 、给脚本添加可执行权限,然后直接就可以执行了

[root@localhost shell]# chmod +x kang.sh 
[root@localhost shell]# ./kang.sh 
Hello world

PS: 脚本是各种命令的集合,终究还是要执行服务的 

查看命令储蓄路径

[root@localhost bin]# echo $PATH
/usr/lib64/qt-3.3/bin:/root/perl5/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
[root@localhost bin]# cat test.sh 
#!/bin/bash
ls /etc/passwd
mkdir /data
cp /etc/passwd /data/
[root@localhost bin]# chmod +x test.sh
[root@localhost bin]# test.sh
/etc/passwd
[root@localhost bin]# 

变量 

顾名思义,变量就是其值可以变化的量。从变量的本质来说,变量名是指向一片用于存储数据的内存空间。变量有局部变量、环境变量之分。在脚本中,往往需要使用变量来存储有用信息,比如文件名、路径名、数值等,通过这些变量可以控制脚本的运行行为

1.局部变量:

是指在某个 shell 中生效的变量,对其他 shell 来说无效,局部变量的作用域被限定在声明它们的shell 中,可以使用 local 内建命令来 显式” 的声明局部变量,但仅限于函数内使用

2.环境变量通常又称全局变量

以区别于局部变量。在 shell 脚本中,变量默认就是全局的,为了让子shell 继承当前 shell 的变量,可以使用 export命令将其定义为环境变量

$PATH UID HOSTNAME PWD (存在内存中的)

3.设置环境变量: 

第一种: declare -x
[root@localhost shell]# declare -x class="Linux base"
[root@localhost shell]# echo $class
Linux base
第二种: export
[root@localhost shell]# export class1="Linux"
[root@localhost shell]# echo $class1
Linux
第三种:
[root@localhost shell]# name="bj"
[root@localhost shell]# echo $name
bj

总结

总结: declare -x export 这种设置变量的方式,是全局的环境变量,(全局环境变量的特点: 子进程会继承父进程的环境变量),第三种" 变量名= 变量值 " 的这种方式,默认只在当前进程有效,如果想要子进程也有效,可以使用前两种暴露的方式,或者,将变量到/etc/profile 文件中,
注意等号左右不能加空格,引号可以是单引号,也可以是双引号 , 当然也可以是引用一条命令执行后的结果( 使用反引号
[root@localhost shell]# name=`cat /etc/fstab`
[root@localhost shell]# echo $name
# # /etc/fstab # Created by anaconda on Wed Nov 2 23:38:14 2022 # # Accessible filesystems, by reference, are maintained under '/dev/disk' # See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info # /dev/mapper/centos-root / xfs defaults 0 0 UUID=1d919f48-cb52-43a9-bacb-9ea0e03a51b7 /boot xfs defaults 0 0 /dev/mapper/centos-swap swap swap defaults 0 0
// 使用反应号之后,显示格式会变化,变成了一行了。那么怎么能够显示正常那?
[root@localhost shell]# echo "$name"

#
# /etc/fstab
# Created by anaconda on Wed Nov  2 23:38:14 2022
#
# Accessible filesystems, by reference, are maintained under '/dev/disk'
# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info
#
/dev/mapper/centos-root /                       xfs     defaults        0 0
UUID=1d919f48-cb52-43a9-bacb-9ea0e03a51b7 /boot                   xfs     defaults        0 0
/dev/mapper/centos-swap swap                    swap    defaults        0 0
[root@localhost shell]# 
// 那么同样还有,变量的值也可以是一个变量
[root@localhost shell]# name=bj
[root@localhost shell]# name2=zs
[root@localhost shell]# name3=$name
[root@localhost shell]# echo $name3
bj
那么问题来了,如果我们现在把 name1 的值改了, name3 的值是否也会跟着改变那?不会
[root@localhost shell]# name1=base
[root@localhost shell]# echo $name3
bj
[root@localhost shell]# 

命名法则举例

studentname====>大驼峰 S tudent N ame, 小驼峰: student N ame (单驼峰 双驼峰 三驼峰)

变量命名

shell 中的变量必须以字母或者下划线开头,后面可以跟数字、字母和下划线,长度没有限制,区分大小写。 " 见名知意 "
变量赋值和取值
定义变量:变量名 = 变量值
注意点1:变量名和变量值之间用等号紧紧相连,之间没有任何空格
[root@localhost shell]# name=lisi
[root@localhost shell]# name= lisi
bash: lisi: 未找到命令...
[root@localhost shell]# 
注意点2:当变量值中有空格时必须用引号括起,否则会出现错误,可以是双引号,也可以是单引号
[root@localhost shell]# name=li lei
bash: lei: 未找到命令...
[root@localhost shell]# 
变量的取值很简单,在变量名前加 $ 号就可以了,严谨的方法是 ${} 。建议用后者
[root@localhost shell]# echo $name
lisi
[root@localhost shell]# echo ${name}
lisi
[root@localhost shell]# 
PS: 这里注意,在很多时候,运行脚本会提示错误,仔细检查脚本后还是不确定哪里出现了问题,那么这时候不妨将变量的取值写成标准格式,说不定就会有惊喜。

取消变量

取消变量使用 unset, 后面跟变量名。函数也是可以被取消的, unset 后面也是可以跟上函数名来取消函数的
[root@localhost shell]# unset name
[root@localhost shell]# echo ${name}

特殊变量

上边我们接触到局部变量和环境(全局)变量,也知道了他们特点:局部变量只在当前shell 有效,环境变量的有效范围为当前 shell 和子 shell 。除了这些还有其他一些变量,也需要我们注意

1、只读变量(常量):

只能声明,但不能修改和删除
[root@localhost shell]# readonly name1="wukong"
[root@localhost shell]# echo $name1
wukong
[root@localhost shell]# name1=bajie
-bash: name1: 只读变量
[root@localhost shell]# 
还可以使用 declare -r 声明常量
[root@localhost shell]# declare -r name2="bajie"
[root@localhost shell]# echo $name2
bajie
[root@localhost shell]# 
readonly: 有效期直到是进程结束。那么这个只读变量有什么用那?比方说pi=3.14 3.1415926

查看常量值

[root@localhost shell]# readonly -p
declare -r BASHOPTS="checkwinsize:cmdhist:expand_aliases:extglob:extquote:force_fignore:histappend:interactive_comments:login_shell:progcomp:promptvars:sourcepath"
declare -ir BASHPID
declare -r BASH_COMPLETION_COMPAT_DIR="/etc/bash_completion.d"
declare -ar BASH_REMATCH='()'
declare -ar BASH_VERSINFO='([0]="4" [1]="2" [2]="46" [3]="2" [4]="release" [5]="x86_64-redhat-linux-gnu")'
declare -ir EUID="0"
declare -ir PPID="4989"
declare -r SHELLOPTS="braceexpand:emacs:hashall:histexpand:history:interactive-comments:monitor"
declare -ir UID="0"
declare -r name1="wukong"
declare -r name2="bajie

括号的使用

小括号用法:一次性使用。不会对环境产生影响

[root@localhost shell]# (name=yjs;echo $name)
yjs
[root@localhost shell]# echo $name

[root@localhost shell]# 
大括号 :前后有空格。这个是对全局有影响的。
[root@localhost shell]# { name=adam; echo $name; }
adam
[root@localhost shell]# echo $name
adam
[root@localhost shell]#

位置变量

shell 中还有一些预先定义的特殊只读变量,它们的值只有在脚本运行时才能确定
$0 :代表脚本本身名字
$1----$9 :第一个位置参数 ------- 9 个位置参数
$# :脚本参数的个数总和
$@ :表示脚本的所有参数
$* : 表示脚本的所有参数
[root@localhost shell]# cat example.sh
#!/bin/bash
echo "这个脚本的名字是:$0"
echo "参数一共有:$#个"
echo "参数的列表是: $@"
echo "参数的列表是: $*"
echo "第一个参数是: $1"
echo "第二个参数是: $2"
echo "第三个参数是:$3"
[root@localhost shell]# 
[root@localhost shell]# bash example.sh 1 2 3 4 5
这个脚本的名字是:example.sh
参数一共有:5个
参数的列表是: 1 2 3 4 5
参数的列表是: 1 2 3 4 5
第一个参数是: 1
第二个参数是: 2
第三个参数是:3
如果有 10 个以上的数改怎么表示
[root@localhost shell]# echo {1..15}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
[root@localhost shell]# echo {a..z}
a b c d e f g h i j k l m n o p q r s t u v w x y z
[root@localhost shell]# 
怎么才能让它识别为$10那?这个时候就要用到花括号了。
[root@localhost shell]# cat example.sh
#!/bin/bash
echo "这个脚本的名字是:$0"
echo "参数一共有:$#个"
echo "参数的列表是: $@"
echo "参数的列表是: $*"
echo "第一个参数是: $1"
echo "第二个参数是: $2"
echo "第三个参数是:$3"
echo "第12个参数是:${12}"
[root@localhost shell]# 
[root@localhost shell]# bash example.sh {1..15}
这个脚本的名字是:example.sh
参数一共有:15个
参数的列表是: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
参数的列表是: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
第一个参数是: 1
第二个参数是: 2
第三个参数是:3
第12个参数是:12
[root@localhost shell]# 
// 那么具体这个有什么用那?,其实可以这样,假设我们要复制一个文件到另一台虚拟机。用什么命令那?scp
[root@localhost shell]# cat /etc/redhat-release > mylrelease.txt
[root@localhost shell]# cat mylrelease.txt
CentOS Linux release 7.9.2009 (Core)
[root@localhost shell]# 

$* $@ 的区别。

$* $@ 都代表了脚本的所有参数,但是, $* 它会把显示的结果当做一个整体显示,而$@ 会把收集到的结果分开来显示。不过要注意,如果$*和 $@ 有双引号的前提下,显示效果会做区分,如果都没有双引号,效果一样。
[root@localhost shell]# cat t1.sh 
#!/bin/bash
echo "t1脚本所有参数是:$*"
bash t2.sh "$*"
[root@localhost shell]# cat t2.sh 
#!/bin/bash
echo "t2脚本的第一个参数:$1"
[root@localhost shell]# bash t1.sh 1 2 3
t1脚本所有参数是:1 2 3
t2脚本的第一个参数:1 2 3
[root@localhost shell]# 
t1.sh 中的 bash t2.sh “$*” 换成 $@ sed 怎么换
[root@localhost shell]# sed -i '3s/\$\*/\$\@/' t1.sh
[root@localhost shell]# bash t1.sh 1 2 3
t1脚本所有参数是:1 2 3
t2脚本的第一个参数:1
[root@localhost shell]# 

$0 引用名称的使用

再来说这个 $0 $0 是名称,那么如果说,我把一个脚本,添加一个软连接。这个时候如果再运行脚本,那么它的$0 显示的名字应该是原来的名字那?还是更改过后的名字?
[root@localhost shell]# ln -s example.sh link.sh
[root@localhost shell]# bash link.sh
这个脚本的名字是:link.sh
参数一共有:0个
参数的列表是: 
参数的列表是: 
第一个参数是: 
第二个参数是: 
第三个参数是:
第12个参数是:
[root@localhost shell]# 
那么以后我们就可以利用这一点,即便是同一个脚本,到时候也可以拓展出不同的功能。比如说,就可以利用这一点。那么就可以让他们返回的值是不一样的。这个就是以后在写脚本的时候,就要注意下,需要对$0 做判断了。

shift命令: 整体往左移位

[root@localhost shell]# cat example.sh
#!/bin/bash
echo "这个脚本的名字是:$0"
echo "参数一共有:$#个"
echo "参数的列表是: $@"
echo "参数的列表是: $*"
echo "第一个参数是: $1"
echo "第二个参数是: $2"
echo "第三个参数是:$3"
echo "第12个参数是:${12}"
shift
echo "这个脚本的名字是:$0"
echo "参数一共有:$#个"
echo "参数的列表是: $@"
echo "参数的列表是: $*"
echo "第一个参数是: $1"
echo "第二个参数是: $2"
echo "第三个参数是:$3"
echo "第12个参数是:${12}"
shift
echo "这个脚本的名字是:$0"
echo "参数一共有:$#个"
echo "参数的列表是: $@"
echo "参数的列表是: $*"
echo "第一个参数是: $1"
echo "第二个参数是: $2"
echo "第三个参数是:$3"
echo "第12个参数是:${12}"
[root@localhost shell]# 
PS : 当然这是默认的移动一位,当然也可以通过设置决定移动多少位,在shift 后边直接加上想要移动的位数即可。

退出状态

进程使用退出状态来报告成功或者失败:
   $ ? 变量保存最近的命令退出状态
   0 代表成功, 1~255 代表失败
举例
[root@localhost shell]# ls /tmp/
systemd-private-5d5242bfa7a445ff929e39dfdd38104b-bolt.service-eJViXd
systemd-private-5d5242bfa7a445ff929e39dfdd38104b-chronyd.service-AhBuTC
systemd-private-5d5242bfa7a445ff929e39dfdd38104b-colord.service-IMbJvs
systemd-private-5d5242bfa7a445ff929e39dfdd38104b-cups.service-N5SsIj
systemd-private-5d5242bfa7a445ff929e39dfdd38104b-rtkit-daemon.service-63nbw5
systemd-private-e403b5d9448d4c048c3a7f654f134ba8-bolt.service-MNeFrF
systemd-private-e403b5d9448d4c048c3a7f654f134ba8-chronyd.service-A8qNGd
systemd-private-e403b5d9448d4c048c3a7f654f134ba8-colord.service-WUjrtE
systemd-private-e403b5d9448d4c048c3a7f654f134ba8-cups.service-eCfKFF
systemd-private-e403b5d9448d4c048c3a7f654f134ba8-rtkit-daemon.service-IQMGcU
yum_save_tx.2023-07-06.15-27.Jcn602.yumtx
[root@localhost shell]# echo $?
0
[root@localhost shell]# ls /apc
ls: 无法访问/apc: 没有那个文件或目录
[root@localhost shell]# echo $?
2
[root@localhost shell]# id test &> /dev/null
[root@localhost shell]# echo $?
1
[root@localhost shell]# 
当然判断命令是否执行成功,不仅仅是简单的判断$? 还有更严谨的判断语句,这个我们以后会讲,现在先知道就可以了。那么在这里还需要知道一点。我们的脚本里边,往往是大于一条命令的,这个$? 返回的 0 值,如果返回的是0, 那么这个 0值到底是返回的哪一条命令的值那?
[root@localhost shell]# cat test1.sh
#!/bin/bash
hostname
[root@localhost shell]# bash test1.sh
localhost.localdomain
[root@localhost shell]# echo $?
0
[root@localhost shell]# 
这是一条命令,如果是多秒命令那 ? ,这里故意将上述明林写错试一下
[root@localhost shell]# cat test1.sh
#!/bin/bash
hostnam
[root@localhost shell]# bash test1.sh
test1.sh:行2: hostnam: 未找到命令
[root@localhost shell]# echo $?
127
[root@localhost shell]# cat test1.sh
#!/bin/bash
hostnam
ls
[root@localhost shell]# bash test1.sh
test1.sh:行2: hostnam: 未找到命令
example.sh  kang.sh  link.sh  mylrelease.txt  t1.sh  t2.sh  test1.sh
[root@localhost shell]# echo $?
0
[root@localhost shell]# 
说明, $? 通常只返回最后一条命令的状态。但不是绝对,因为还有另外一种情况。比如语法错误
[root@localhost shell]# cat test1.sh
#!/bin/bash
if
ls
[root@localhost shell]# bash test1.sh
test1.sh:行4: 语法错误: 未预期的文件结尾
[root@localhost shell]# echo $?
2
[root@localhost shell]# 
再还有,只要返回的不是 0 ,肯定是错误的那?也是不一定的。因为 $? 的返回值,是可以修改的。
正常的 $0
[root@localhost shell]# cat test1.sh
#!/bin/bash
ls
[root@localhost shell]# bash test1.sh
example.sh  kang.sh  link.sh  mylrelease.txt  t1.sh  t2.sh  test1.sh
[root@localhost shell]# echo $?
0
[root@localhost shell]# 
修改退出状态码
[root@localhost shell]# cat test1.sh 
#!/bin/bash
ls
exit 10
[root@localhost shell]# bash test1.sh
example.sh  kang.sh  link.sh  mylrelease.txt  t1.sh  t2.sh  test1.sh
[root@localhost shell]# echo $?
10
[root@localhost shell]# 
PS : 那么我们就要考虑,根据不同的返回码,我们是不是就可判断出系统的运行状态啊? 假设说,我们规定了计算机会有几种情况,如果说一种情况返回10 ,另一种情况返回 20 ,还有 30 ,那么我们就可根据系统返回的值的不同,来判断出,系统肯定是满足了某种条件。这样就可以作为定位判断系统状态的依据,其实在我们上网的时候有返回发 404 ,其实也是类似这种方法的。200 OK 404 Not Found3xx重定向 4xx 客户端错误 5xx 服务器错误当然exit 命令在外部也可以使用,意思是退出 bash

你可能感兴趣的:(liunx,linux)