Shell基础 01

本文涉及的产品
对象存储 OSS,标准 - 本地冗余存储 20GB 3个月
对象存储 OSS,内容安全 1000 次 1年
文件存储 NAS,50GB 3个月
简介: Shell 是一种脚本语言,用于操作 Linux 服务器。本文介绍了 Shell 变量的定义和作用域,以及多命令运行的练习。变量定义时需注意字符串的引用方式,变量可分为局部和全局。多命令运行中,通过逻辑运算符 `&&` 和 `||` 实现条件判断和命令执行。

 shell 是一种脚本语言,该语言提供了对linux服务器进行操作的命令集合及逻辑处理方式。

1.shell变量定义

在定义变量时,若string中包含空格、制表符和换行符,则string必须用 'string' 或者 "string"的形式,即用单(双)引号将其括起来。双引号内允许变量替换,而单引号内则不可以。

下面给出一个定义和使用shell变量的例子。

//显示字符常量
[root@RHEL7-1 ~]# echo who are you
who are you
[root@RHEL7-1 ~]# echo 'who are you'  
who are you
[root@RHEL7-1 ~]# echo "who are you"
who are you
[root@RHEL7-1 ~]#
//由于要输出的字符串中没有特殊字符,所以' '和" "的效果是一样的,不用""但相当于使用了""
[root@RHEL7-1 ~]# echo Je t'aime
> 
//由于要使用特殊字符('),
//由于'不匹配,shell认为命令行没有结束,回车后会出现系统第二提示符,
//让用户继续输入命令行,按“Ctrl+C”组合键结束
[root@RHEL7-1 ~]#
//为了解决这个问题,可以使用下面的两种方法
[root@RHEL7-1 ~]# echo "Je t'aime"
Je t’aime
[root@RHEL7-1 ~]# echo Je t\'aime

image.gif

2.shell变量的作用域

与程序设计语言中的变量一样,shell变量也有规定的作用范围。shell变量分为局部变量和全局变量。

  • 局部变量的作用范围仅限命令行所在的shell或shell脚本文件中。
  • 全局变量的作用范围则包括本shell进程及其所有子程序。
  • 可以使用export内置命令将局部变量设置为全局变量。
//在当前shell中定义变量var1
[root@RHEL7-1 ~]# var1=Linux
//在当前shell中定义变量var2并将其输出
[root@RHEL7-1 ~]# var2=unix
[root@RHEL7-1 ~]# export var2
//引用变量的值
[root@RHEL7-1 ~]# echo $var1
Linux
[root@RHEL7-1 ~]# echo $var2
unix
//显示当前shell的PID
[root@RHEL7-1 ~]# echo $$
2670
[root@RHEL7-1 ~]#
//调用子shell
[root@RHEL7-1 ~]# bash
//显示当前shell的PID
[root@RHEL7-1 ~]# echo $$
2709                   
//由于var1没有被输出,所以在子shell中已无值
[root@RHEL7-1 ~]# echo $var1
//由于var2被输出,所以在子shell中仍有值
[root@RHEL7-1 ~]# echo $var2
unix
//返回主shell,并显示变量的值
[root@RHEL7-1 ~]# exit
[root@RHEL7-1 ~]# echo $$
2670
[root@RHEL7-1 ~]# echo $var1
Linux
[root@RHEL7-1 ~]# echo $var2
unix
[root@RHEL7-1 ~]#

image.gif

3.多命令运行练习

我们有如下情况。

  1. 先判断一个目录是否存在。
  2. 若存在,则在该目录下面创建一个文件。
    由于我们尚未介绍“条件判断式(test)”的使用,在这里我们使用ls以及回传值来判断目录是否存在。让我们进行下面的练习。

【例7-1】使用ls查阅目录/tmp/abc是否存在,若存在,则用touch创建/tmp/abc/hehe。

[root@RHEL7-1 ~]# ls /tmp/abc && touch /tmp/abc/hehe
ls: cannot access /tmp/abc: No such file or directory 
# 说明找不到该目录,但并没有touch的错误,表示touch并没有运行
[root@RHEL7-1 ~]# mkdir  /tmp/abc
[root@RHEL7-1 ~]# ls  /tmp/abc  &&  touch  /tmp/abc/hehe
[root@RHEL7-1 ~]# ll  /tmp/abc
total 0
-rw-r--r--. 1 root root 0 Jul 14 22:34 hehe

image.gif

如果/tmp/abc不存在时,touch就不会被运行;若/tmp/abc存在,那么touch就会开始运行。在上面的例子中,我们还必须手动自行创建目录,很麻烦。能不能自动判断:如果没有该目录就创建呢?看下面的例子。

【例7-2】测试/tmp/abc是否存在,若不存在,则予以创建;若存在,就不做任何事情。

[root@RHEL7-1 ~]# rm  -r  /tmp/abc                 // <==先删除此目录以方便测试
[root@RHEL7-1 ~]# ls  /tmp/abc  ||  mkdir  /tmp/abc
ls: /tmp/abc: No such file or directory <==真的不存在
[root@RHEL7-1 ~]# ll  /tmp/abc
Total      0                               // <==结果出现了,说明运行了mkdir命令

image.gif

如果一再重复“ls /tmp/abc || mkdir /tmp/abc”,也不会出现重复mkdir的错误。这是因为/tmp/abc已经存在,所以后续的mkdir就不会进行。

再次讨论:如果想要创建/tmp/abc/hehe这个文件,但是并不知道 /tmp/abc是否存在,那该如何办呢?

【例7-3】如果不管/tmp/abc存在与否,都要创建/tmp/abc/hehe文件,怎么办呢?

[root@RHEL7-1 ~]#ls /tmp/abc  ||  mkdir  /tmp/abc  &&  touch  /tmp/abc/hehe

image.gif

上面的例7-3总是会创建/tmp/abc/hehe,不论/tmp/abc是否存在。那么例7-3应该如何解释呢?由于Linux下面的命令都是由左往右执行的,所以例7-3有下面两种结果。

  1. 若/tmp/abc不存在。回传$?≠0;因为||遇到非为0的$?,故开始执行mkdir /tmp/abc,由于mkdir /tmp/abc会成功执行,所以回传 $?=0;因为&&遇到 $?=0,故会执行touch /tmp/abc/hehe,最终hehe就被创建了。
  2. 若/tmp/abc存在。回传 $?=0;因为||遇到 $?=0不会执行,此时 $?=0继续向后传;因为&&遇到 $?=0就开始创建/tmp/abc/hehe,所以最终/tmp/abc/hehe被创建。

整个流程如下图所示。

image.gif 编辑

上面这张图显示的两股数据中,上方的线段为不存在 /tmp/abc时所进行的命令行为,下方的线段则是存在/tmp/abc时所进行的命令行为。如上所述,下方线段由于存在 /tmp/abc所以导致 $?=0,中间的mkdir就不运行了,并将 $?=0继续往后传给后续的touch去利用。

我们再来看看下面这个例题。

【例7-4】以ls测试/tmp/bobbying是否存在:若存在,则显示“exist”;若不存在,则显示“not exist”。

这又牵涉到逻辑判断的问题,如果存在就显示某个数据,若不存在就显示其他数据,那么我们可以这样做:

ls /tmp/bobbying && echo "exist" || echo "not exist"

意思是说,在ls /tmp/bobbying运行后,若正确,就运行echo "exist",若有问题,就运行echo "not exist"。那如果写成如下的方式又会如何呢?

ls /tmp/bobbying || echo "not exist" && echo "exist"

这其实是有问题的,为什么呢?由图7-2的流程介绍,我们知道命令是一个一个往后执行,因此在上面的例子中,如果/tmp/bobbying不存在时,会进行如下动作。

① 若ls /tmp/bobbying不存在,则回传一个非0的数值。

② 接下来经过||的判断,发现前一个命令回传非0的数值,因此,程序开始运行echo "not exist",而echo "not exist" 程序肯定可以运行成功,因此会回传一个0值给后面的命令。

③ 经过&&的判断,所以就开始运行echo "exist"。

这样,在这个例子里面竟然会同时出现not exist与exist,是不是很有意思啊!请读者仔细思考。

特别提示:经过这个例题的练习,你应该了解,由于命令是一个接着一个运行的,因此,如果真要使用判断,那么 && 与 || 的顺序就不能搞错。一般来说,假设判断式有3个,也就是,command1 && command2 || command3,而且顺序通常不会变。因为一般来说,command2与command3会放置肯定可以运行成功的命令,因此,依据上面例题的逻辑分析,必须按此顺序放置各命令,请读者一定注意。

相关文章
|
存储 网络协议 Ubuntu
【C++网络编程】Socket基础:网络通讯程序入门级教程
【C++网络编程】Socket基础:网络通讯程序入门级教程
436 7
|
SQL 关系型数据库 MySQL
TiDB支持的SQL语法概述
【2月更文挑战第28天】本章将对TiDB所支持的SQL语法进行概述,涵盖其主要的语法特性和功能。我们将从基本的SQL语句到更复杂的查询和操作,逐步介绍TiDB的SQL语法,帮助读者更好地理解和使用TiDB进行数据库操作。
1160 0
|
2月前
|
监控 Cloud Native Java
GraalVM 原生镜像技术详解与实践指南
本文档全面介绍 GraalVM 原生镜像技术的核心概念、架构设计和实践应用。作为革命性的 Java 运行时技术,GraalVM 原生镜像通过提前编译(AOT)将 Java 应用程序编译为本地可执行文件,显著提升了启动性能和资源利用率。本文将深入探讨其工作原理、构建流程、性能优化以及与云原生环境的集成,帮助开发者构建新一代高性能 Java 应用。
227 0
|
11月前
|
Python
socket 服务
本示例展示了如何使用 Python 的 socket 模块创建一个简单的服务器。服务器绑定到本地主机的 12345 端口,监听客户端连接请求,并向每个连接的客户端发送欢迎消息,然后关闭连接。
258 59
|
缓存 网络协议 Linux
c++实战篇(三) ——对socket通讯服务端与客户端的封装
c++实战篇(三) ——对socket通讯服务端与客户端的封装
486 0
|
10月前
|
网络协议 C# 开发工具
C#中简单Socket编程
1. 先运行服务器代码。服务器将开始监听指定的IP和端口,等待客户端连接。 1. 然后运行客户端代码。客户端将连接到服务器并发送消息。 1. 服务器接收到消息后,将回应客户端,并在控制台上显示接收到的消息。 1. 客户端接收到服务器的回应消息,并在控制台上显示。
501 15
|
11月前
|
网络协议
Socket 对象(内建)方法
Socket 对象(内建)方法。
161 15
|
缓存 监控 网络协议
c++高级篇(二) ——Linux下IO多路复用之select模型
c++高级篇(二) ——Linux下IO多路复用之select模型
266 1
|
SQL API 数据库
为API设置默认排序规则结果数据的正确性
Dataphin数据服务支持API调用时通过OrderByList自定义排序,确保数据返回符合业务需求。默认排序在API设计时至关重要,因为它影响用户体验、数据一致性及查询正确性。新版本 Dataphin 提供了排序优先级设置,允许在SQL脚本或OrderByList中指定排序,以适应不同场景。
272 0

热门文章

最新文章