自学内容网 自学内容网

shell

  • 大概历时1个多月,一直在输入、琢磨有关linux-shell的鸡毛碎皮。单从目前来看收益甚微,因为大部分人的惯用做法是碰到不会的查一下,而不会专门的去学习。但从长远来看,我对shell有了宏观的了解,起码知道具体该查什么命令,而不是仅仅把问题的现象扔给度娘。下面推荐一个shell文档、一个命令行搜索工具、一个bash网站,这些都是师兄推荐、我用过并认为不错的。
  • 接下来的时间,会向数学靠拢,具体学习方向是数理统计及机器人状态估计。

推荐资料
shell文档及拓展阅读
Linux命令搜索引擎
Linux入门自学网

1. 通配符

通配符意义
*匹配任意多个字符(包括零个或一个)
匹配任意一个字符(不包括零个)
[characters]匹配任意一个属于字符集(characters)中的字符
[!characters]匹配任意一个不是字符集中的字符
[[:class:]]匹配任意一个属于指定字符类中的字符
[:alnum:]——匹配任意一个字母或数字
[:alpha:]——匹配任意一个字母
[:digit:]——匹配任意一个数字
[:lower:]——匹配任意一个小写字母
[:upper:]——匹配任意一个大写字母
通配符范例匹配对象
g*文件名以“g”开头的文件
b*.txt以"b"开头,中间有零个或任意多个字符,并以".txt"结尾的文件
Data???以“Data”开头,其后紧接着3个字符的文件
[abc]*文件名以"a",“b”,或"c"开头的文件
BACKUP.[0-9][0-9][0-9]以"BACKUP."开头,并紧接着3个数字的文件
*[[:lower:]123]文件名以小写字母结尾,或以 “1”,“2”,或 “3” 结尾的文件

2. 创建链接(ln)

ln 命令既可创建硬链接ln file link,也可以创建符号链接(软链接)ln -s item link

硬链接 & 软链接 区别:

  • 一个硬链接不能关联它所在文件系统之外的文件。这是说一个链接不能关联与链接本身不在同一个磁盘分区上的文件。
  • 一个硬链接不能关联一个目录。
  • 软链接可以对一个不存在的文件名进行链接,硬链接不可以。

硬链接:

mkdir playground
cd playground
mkdir dir1 dir2
cp /home/zixie/hello.sh .
ln hello.sh hello_hard
ln hello.sh dir1/hello_hard1
ln hello.sh dir2/hello_hard2

在这里插入图片描述

  • 列表中,文件 hello_hard 和 hello.sh 的第二个字段是”4”,这个数字是文件”hello.sh”的硬链接数目。一个文件至少有一个硬链接,因为文件名就是由链接创建的。由于linux下的文件是通过索引节点(Inode)来识别文件,硬链接可以认为是一个指针,指向文件索引节点的指针,系统并不为它重新分配inode。每添加一个硬链接,文件的链接数就加1。
    在这里插入图片描述
  • 硬连接之间没有主次之分,都具有独立性,删除某个硬链接(包括源文件),不会删除inode,其余硬链接不受影响。

软链接:

cd playground
ln -s hello.sh hello_sym
ln -s ../hello.sh dir1/hello_sym1
ln -s ../hello.sh dir2/hello_sym2

在这里插入图片描述

  • 软连接会产生新的inode,因此源文件的链接数不会增加。软链接的inode指向数据块保存的原文件路径(hello.sh刚好8个字节),因此不会因hello_sym文件大小的改变而改变。
  • 对于符号链接文件,剩余的文件属性总是"rwxrwxrwx",而且都是虚拟值。真正的文件属性是指符号链接所指向的文件的属性。
  • ls -li第二字段开头:d表示目录、-表示普通文件、l表示符号链接、c表示字符设备文件(这种文件类型是指按照字节流来处理数据的设备,比如ttyS0)、b表示块设备文件(这种文件类型是指按照数据块来处理数据的设备,例如一个硬盘)、p表示命名管道(通过mkfifo命令创建命名管道)、rwxrwxr-x表示文件所有者(第三字段zixie)和所属组(第四字段zixie)有读写执行权限,其他用户只有读和执行权限,没有写的权限。
  • 创建的软链接(hello_sym)指向的源文件(hello.sh),默认会以软链接hello_sym的路径为根,去寻找指向的文件hello.sh,所以创建时,请以软链接的路径作为起点路径去写原文件的相对路径(当然,使用绝对路径就不用考虑本条了)。
    在这里插入图片描述
  • 删除源文件后,软链接损坏,变为红色,而硬链接不受影响。
    在这里插入图片描述

3. 用别名创建自己的命令(alias)

# 展示一个命令行小技巧。可以把多个命令放在同一行上,命令之间用”;”分开
cd 桌面;touch test.txt;cd -
# 上述联合了3个命令:进入桌面,新建test.txt文件,返回之前目录

① 通过alias命令把这一串命令转变为一个命令A之前,先查明A是否已经在系统中定义了,命令为type A

type - 显示命令的类型

命令可以是下面四种形式之一:

  • 一个可执行程序,就像我们所看到的位于目录/usr/bin 中的文件一样。 这一类程序可以是用诸如 C 和 C++ 语言写成的程序然后编译得到的二进制文件, 也可以是由诸如 shell,perl,python,ruby 等等脚本语言写成的程序。
  • 一个内建于 shell 自身的命令。bash 支持若干命令,内部叫做 shell 内部命令 (builtins)。例如,cd 命令,就是一个 shell 内部命令。
  • 一个 shell 函数。这些是小规模的 shell 脚本,它们混合到环境变量中。 在后续的章节里,我们将讨论配置环境变量以及书写 shell 函数。但是现在, 仅仅意识到它们的存在就可以了。
  • 一个命令别名。我们可以定义自己的命令,建立在其它命令之上。
    在这里插入图片描述

② 创建命令别名alias lucky='cd 桌面;touch test.txt;cd -'(命令结构:alias name='string'),使用type lucky查看命令类型(使用unalias lucky删掉自定义命名令).
在这里插入图片描述
③ 此命令别名只在本shell窗口下有效,要想所有终端都适配,加入.bashrc中:echo "alias lucky='cd 桌面;touch test.txt;cd -'" >> ~/.bashrc

要查看所有定义在系统环境中的别名,可以直接使用alias
在这里插入图片描述

4. I/O重定向

默认情况下,程序及命令产生的标准输出stdout标准错误输出stderr都连接到屏幕,标准输入stdin连接到键盘,I/O 重定向允许我们更改输出地点和输入来源。

  • 标准输出重定向( “>” 重定向符)
ls -l /usr/bin > ls-output.txt  //标准输出由屏幕重定向到文件ls-output.txt

当我们使用 “>” 重定向符来重定向输出结果时,目标文件总是从开头被重写,如果我们需要清空一个文件内容(或者创建一个新的空文件),输入命令:> ls-output.txt。若要追加内容到文件内容后面,而不是从开头重写文件,使用”>>“重定向符ls -l /usr/bin >> ls-output.txt

  • 标准错误输出重定向(“2”文件描述符)

补充:一个程序的输出会流入到几个带编号的文件中。这些文件的前三个称作标准输入、标准输出和标准错误输出,shell内部分别将其称为文件描述符0、1和2。

ls -l /bin/usr 2> ls-error.txt  //目录/bin/usr不存在,如果不加文件描述符2,标准错误仍会输出到屏幕上

扔掉一个命令的错误输出ls -l /bin/usr 2> /dev/null,/dev/null文件是系统设备,叫做数字存储桶,它可以接受输入,并且对输入不做任何处理。

  • 标准输出和错误重定向到同一个文件
# 法一:传统的方法, 在旧版本 shell 中也有效
ls -l /bin/usr > ls-output.txt 2>&1  //完成两个重定向:1.重定向标准输出到文件ls-output.txt 2.重定向文件描述符2(标准错误输出)到文件描述符1(标准输出)
#  ls -l /bin/usr 2>&1 > ls-output.txt  二者位置更换后失效,标准错误输出仍然到屏幕,标准输出到文件 ls-output.txt

# 法二:目前bash版本
ls -l /bin/usr &> ls-output.txt  //单单一个表示法 &> 来重定向标准输出和错误到文件 ls-output.txt
  • 标准输入重定向(“<”重定向操作符)
命令作用
cat/less [file]读取一个或多个文件,然后复制它们到标准输出(屏幕)
cat从标准输入(键盘)(Ctrl-d提示标准输入到达文件末尾EOF)读入数据,输出到标准输出(屏幕)
cat > lucky.txt通过键盘创建简短的文本文件lucky.txt
cat < lucky.txt使用“<”重定向操作符,我们把标准输入源从键盘改到文件lucky.txt,效果类似于cat lucky.txt
管道操作符"|"一个命令的标准输出可以通过管道送至另一个命令的标准输入
grep用来找到文件中的匹配文本
ls | grep lucky在当前目录下找包含lucky文本的文件
ls | grep -i lucky在执行搜索时忽略大小写
head / tail打印文件开头部分/结尾部分(默认打印前/后10行文本) ,可以通过”-n”选项来调整命令打印的行数
head -n 5 lucky.txt打印lucky.txt开头的前5行
ls | tail -n 5打印当前目录下的后5行
tee从标准输入读入数据,并且同时复制数据到标准输出(允许数据继续随着管道线流动)和一个或多个文件
ls /usr/bin | tee ls.txt | grep zip/usr/bin目录下的内容:1.全部输出到文件ls.txt 2.屏幕上(标准输出)输出含有zip的内容

5. 更改文件或目录的权限(chmod)

文件和目录的权限属性:
在这里插入图片描述

chmod 命令支持两种不同的方法来改变文件/目录模式:八进制数字表示法符号表示法

八进制数字表示法
每个八进制数字代表了 3个二进制数字,八进制和文件权限映射关系如下:
在这里插入图片描述
sudo chmod 000 hello.sh删除文件所有组,用户组和其他用户的读、写和执行权限。
在这里插入图片描述

符号表示法
符号表示法分为三部分:更改会影响谁(u g o a), 要执行哪个操作(+ -),要设置哪种权限(r w x)。

  • u g o a 指代:
    在这里插入图片描述
    (若没有指定作用对象,则默认使用”all”)
  • 执行操作“+”字符表示加上一个权限; “-”字符表示删掉一个权限;“=”字符表示只有指定的权限可用,其它所有的权限被删除。
    在这里插入图片描述

6. 以其他用户身份和组ID运行一个shell(adduser su)

  • 首先需要创建一个用户
sudo adduser hzx  //会自动为创建的用户指定主目录、系统shell版本,会在创建时输入用户密码

sudo passwd hzx  //改用户hzx的密码

sudo deluser hzx  //只删除用户
sudo deluser --remove-home hzx  //连同用户的主目录和邮箱一起删除
sudo deluser --remove-all-files hzx  //连同用户拥有的所有文件删除

cat /etc/passwd  //显示系统中的所有用户信息
# zixie:x:1000:1000:zixie,,,:/home/zixie:/bin/bash  
# 用户名:密码字段(存于/etc/shadow中):UID:GID:用户信息字段(用户的全名、房间号、工作电话和住宅电话):用户的主目录:用户的默认登录shell
  • su命令简单使用
sudo su -  # 切换到root用户(在/root路径下化身超级用户)(提示符的末尾字符是”#”而不是”$”)
sudo su  # 切换到root用户(在当前路径下化身超级用户)(Ctrl+d / exit退出)
su -l [other_user]  # 切换用户并改变环境变量和工作目录
su -c 'ls -l' [other_user]  # 以其他用户身份运行'ls -l'命令,然后退出
  • 相比于su命令,sudo命令不要求超级用户的密码。使用sudo命令时,用户使用他/她自己的密码来认证。
  • su和sudo之间的一个重要区别是sudo不会重新启动一个shell,也不会加载另一个用户的shell运行环境。
  • 当引进Ubuntu的时候,它的创作者们采取了不同的策略。默认情况下,Ubuntu不允许用户登录到root帐号(因为不能为 root 帐号设置密码),而是使用sudo命令授予普通用户超级用户权限。 通过sudo命令,最初的用户可以拥有超级用户权限,也可以授予随后的用户帐号相似的权力。

7. shell环境

在这里插入图片描述

shell启动顺序:

① 登录系统后,bash程序启动,读取一系列称为启动文件的配置脚本(这些文件定义了默认的可供所有用户共享的shell环境)。
② 然后是读取当前用户家目录中的启动文件(这些启动文件定义了用户个人的shell环境)。

确切的启动顺序依赖于要运行的shell会话类型。有两种shell会话类型:一个是登录shell会话,另一个是非登录shell会话

  • 登录shell会话(远程shell终端)的启动文件:/etc/profile:应用于所有用户的全局配置脚本;~/.profile:用户个人的启动文件,可以用来扩展或重写全局配置脚本中的设置(~/.profile 会读取 ~/.bashrc 的内容)。
  • 非登录 shell 会话的启动文件:/etc/bash.bashrc:应用于所有用户的全局配置文件;~/.bashrc:用户个人的启动文件,可以用来扩展或重写全局配置脚本中的设置。

当编辑一个重要的配置文件时,首先创建一个这个文件的备份,以防万一:cp .bashrc .bashrc.bak(扩展名.bak.sav.old.orig 都是用来指示备份文件的流行方法)

8. 文件压缩与归档

gzip压缩文件(bzip2 bunzip2 bzcat (舍弃压缩速度,实现更高级别的压缩) 和 gzip 使用大致相同)(二者均只可压缩文件,要想压缩文件夹得先tar打包)

  • gzip hello.sh 原始文件hello.sh已经被压缩文件hello.sh.gz替代,保留相同的权限和时间戳
  • gzip -d hello.sh.gzgunzip hello.sh.gz 解压缩
  • 预览压缩文件
gunzip -c hello.sh.gz  # 预览hello.sh.gz输出到屏幕(不解压缩文件,只是预览)
gunzip -c hello.sh.gz | less  # 通过less预览hello.sh.gz
zcat hello.sh.gz  # 预览hello.sh.gz输出到屏幕
zless hello.sh.gz  # 通过less预览hello.sh.gz

压缩时,文件中会被添加描述此次压缩过程的信息。如果再次压缩已经压缩过的文件,因压缩文件已不包含多余信息的文件,再次压缩将不会节省空间以抵消额外的花费,实际上会得到一个更大的文件。
zip既是压缩工具,也是打包工具(可以压缩文件夹)

  • zip -r playground.zip playground压缩(若不包含-r,则只有playground目录,不包含任何内容)
  • unzip -l plground.zip 预览压缩文件
  • unzip plground.zip解压缩

tar归档:收集许多文件,并将其捆绑成一个大文件的过程

# 生成多个文件夹和文件
mkdir -p /playground/dir-{00{0..9},0{10..99},100}  # 生成100个文件夹dir-000-dir-100
touch /playground/dir-{00{0..9},0{10..99},100}/file-{A..Z}

tar一共四大模式:c(创建归档文件),x(抽取归档文件),r(追加具体的路径到归档文件的末尾),t(列出归档内容),在模式后跟选项(eg:f-指定归档文件名称)。

  • tar cf playground.tar playground 打包(c-创建归档文件;f-指定tar包的名字)
  • tar tf playground.tar 列出归档的内容 tar tvf playground.tar 详细列出归档的内容
  • tar xf playground.tar 抽取归档文件(解归档) (tar包仍然存在)
  • 归档中的路径问题:tar cf playground.tar ~/playground 使用绝对路径~/playground,再次抽取归档后tar xf playground.tar,目标在当前抽取路径/home/zixie/playground路径下。
    在这里插入图片描述
  • 选择性抽取:tar xf ../playground.tar --wildcards 'home/zixie/playground/dir-*/file-A'(采用绝对路径归档),只抽取file-A.
    在这里插入图片描述
  • 选择性归档:find playground -name 'file-A' -exec tar rf playground.tar '{}' '+'exec- find命令的执行选项,允许对找到的每个文件执行指定的命令,这里指唤醒带有追加模式(r)的tar命令; {}-exec 命令中的一个占位符,代表find命令找到的每个文件的路径;+ -告诉find命令尽可能地将多个找到的文件名作为参数传递给exec指定的命令,直到达到系统对命令行长度的限制;r-追加具体的路径到归档文件的末尾)
    在这里插入图片描述

先归档再压缩

  • find playground -name 'file-A' | tar cf - --files-from=- | gzip > playground.tgz 使用“-”表示标准输入/输出,f -: 使用标准输出(用 - 表示)作为归档文件,而不是在文件系统上创建一个文件;--files-from=-(-T -): 从标准输入读取要包含在归档中的文件列表(这个输入来自 find 命令的输出)。最后输出playground.tgz(playground.tar.gz)
  • find playground -name 'file-A' | tar czf playground.tgz -T -c模式后添加选项z,使用gzip压缩tar文件;同理,tar xzf playground.tgz也可一键解归档解压缩。
    *find playground -name 'file-A' | tar cjf playground.tbz -T -c模式后添加选项j,使用bzip2压缩tar文件;同理,tar xjf playground.tbz也可一键解归档解压缩

9. 正则表达式

  • 元字符^ $ . [ ] { } - ? * + ( ) | \,其它所有字符都被认为是原义字符。(反斜杠\会被用来创建元序列, 或把元字符转义为原义字符)
  • 圆点字符字符.:圆点字符用来匹配任意字符。grep -h '.zip' dirlist*.txt在dirlist*.txt中查找,返回bunzip2、bzip2…(不返回zip,因为zip只包含3个字符)

grep选项
-i忽略大小写(匹配文件名:匹配项) -v输出不匹配项的文本行(不匹配文件名:不匹配项) -c输出匹配的数量(匹配/不匹配文件名:匹配数量/0) -l只打印包含匹配项的文件名 -L只打印不包含匹配项的文件名 -n输出匹配项位于文件中的相应行号(匹配文件名:匹配行:匹配项) -h应用于多文件搜索,只输出文本行

  • 锚点^ $:正则表达式grep ^zip$ dirlist-* 中,插入符号位于开头和美元符号位于末尾被看作是锚点。
  • 中括号表达式:从一个指定的字符集合中匹配单个字符,grep [bg]zip dirlist-*输出bzip2、gzip…
  • 中括号表示式中第一个字符是一个插入字符(^)表否定,则剩余的字符被看作是不会在给定的字符位置出现的字符集合,grep [^bg]zip dirlist-*,输出bunzip2、gunzip…
  • 连字符-grep -h '^[A-Za-z0-9]' dirlist*.txt,匹配所有以字母和数字开头的文件名。

POSIX 把正则表达式的实现分成了两类: 基本正则表达式(BRE)和扩展的正则表达式(ERE),BRE辨别^ $ . [ ] *,ERE 添加了( ) { } ? + |。在 BRE 中,字符“(”,“)”,“{”,和 “}”用反斜杠转义后,被看作是元字符, 相反在 ERE 中,在任意元字符之前加上反斜杠会导致其被看作是一个文本字符。
② 满足POSIX和BRE的程序有grep,满足POSIX和ERE的程序有egrepgrep -E

  • ERE特性交替|:允许从一系列表达式之间选择匹配项,echo "AAA" | grep -E 'AAA|BBB',输出AAA。
  • ERE特性限定符? - 匹配零个或一个元素;* - 匹配零个或多个元素;+ - 匹配一个或多个元素,要求前面的元素至少出现一次匹配;{ } - 匹配特定个数的元素。
    echo "(555) 123-4567" | grep -E '^\(?[0-9]{3}\)? [0-9]{3}-[0-9]{4}$',ERE\(?转义(出现0次或1次;[0-9]{3}0-9的数字出现3次,输出(555) 123-4567

10. 编写shell脚本

Shell不仅是一个功能强大的命令行接口,也是一个脚本语言解释器

初出茅庐:vim hello_world编写一个简单的shell脚本

#!/bin/bash
# This is our first script.
echo 'Hello World!'
  • #!字符序列是一种特殊的结构叫做 shebang,用来告诉操作系统将执行此脚本所用的解释器的名字,默认在第一行。
  • 写好脚本后,使用 chmod 命令增加可执行权限chmod 755 hello_world
  • 运行脚本,必须指定脚本文件明确的路径./hello_world,或者更改脚本存储位置,把hello_world放到~/bin目录下(系统会通过PATH 环境变量查找可执行程序)。
    在这里插入图片描述
    (若PATH变量不包括此目录,把export PATH=~/bin:"$PATH"添加到.bashrc中,使用. .bashrc / source .bashrc更新,点.命令是 source 命令的同义词,一个shell内建命令)

小试牛刀:编写HTML网页脚本

  • 法一:使用echo " "输出,vim foo.sh
#!/bin/bash
# Program to output a system information page
TITLE="System Information Report For $HOSTNAME" 
CURRENT_TIME=$(date +"%x %r %Z")  # %x: 表示本地日期格式;%r:表示12小时制的时间;%z:表示时区的名称
TIME_STAMP="Generated $CURRENT_TIME, by $USER"
echo "<HTML>
     <HEAD>
               <TITLE>$TITLE</TITLE>
       </HEAD>
      <BODY>
               <H1>$TITLE</H1>
               <P>$TIME_STAMP</P>
       </BODY>
</HTML>"

chmod 755 foo.sh添加执行权限,./foo.sh标准输出到屏幕;./foo.sh > foo.html把输出重定向到文件,通过网络浏览器来查看输出结果:①在浏览器输入URLfile:///home/zixie/foo.html(file:// 是一种 URI统一资源标识符,专门用于指定本地文件的路径) ②终端输入firefox foo.html

  • 法二:here document,格式为command << token [换行]text[换行] tokencommand是一个可以接受标准输入的命令名,token是一个用来指示嵌入文本结束的字符串。
#!/bin/bash
# Program to output a system information page
TITLE="System Information Report For $HOSTNAME"
CURRENT_TIME=$(date +"%x %r %Z")
TIME_STAMP="Generated $CURRENT_TIME, by $USER"
cat << _EOF_  # <<表明是here document格式
<HTML>
        <HEAD>
               <TITLE>$TITLE</TITLE>
        </HEAD>
        <BODY>
               <H1>$TITLE</H1>
               <P>$TIME_STAMP</P>
       </BODY>
</HTML>
_EOF_

效果如下图所示:
在这里插入图片描述

厚积薄发:

  • 编写shell函数

① 直接在脚本中编写shell函数

#!/bin/bash
# 本文件保存路径:/home/zixie/bin/test20240924_1(echo $PATH 输出路径环境变量,可看到该/home/zixie/bin环境变量)
# 函数形式一
function func1 { 
echo "func1"
return
}
# 函数形式二
func2 () {
echo "func2"
return
}

echo "func0"
func1
func2
echo "func3"
# 终端输出:
# func0
# func1
# func2
# func3

② 在/home/zixie/bin中编写脚本,实现函数调用

#!/bin/bash
# 本文件保存路径:/home/zixie/bin/func1
echo "func1"
#!/bin/bash
# 本文件保存路径:/home/zixie/bin/func2
echo "func2"
#!/bin/bash
# 本文件保存路径:/home/zixie/bin/test20240924_2
echo "func0"
func1
func2
echo "func3"
# 终端输出:
# func0
# func1
# func2
# func3

.bashrc文件中的shell函数
同在shell脚本中编写的shell函数,把函数写入.bashrcsource .bashrc更新变量后,新打开任意个终端输入func1,均可以正常输出;若想在shell脚本中调用的话,需要在.bashrc中加入export -f func1(Ubuntu中图形化显示界面通过CTRL+ALT+t 产生的新终端模拟器与之前的shell父终端并行独立,但新终端会运行.bashrc继承环境变量)

  • 局部变量local foo=1通过关键字local定义局部变量.
  • linux中命令执行成功后,返回0;执行失败后返回非0值:命令执行后,终端输入echo $?,如果返回0,则运行成功。脚本中出现exit,退出状态默认为零;exit 1用来表示一种错误情况或异常状态.
  • if分支
#!/bin/bash 
if test -e hello.sh ; then  # 等价于 if  [-e hello.sh] ; then 该文件表达式的含义:是否存在该文件
echo "heelo.sh exist"
fi

# 除了能测试文件表达式,还可以测试字符串表达式、整数表达式
if [-z "zixieshanyi"] ; then  # 该字符表达式的含义:字符串是否为0
echo "the string is not example"
fi 

if [5 lt 10]; then  # 该整数表达式的含义:5 less than 10
echo "true"
fi

复合命令[[ ]]test expression / [expression]的加强版,除了支持[]的功能外,①增加了一个新的字符串表达式string =~ regex判断string是否符合正则表达式;②添加的==操作符支持类型匹配

#!/bin/bash
INT = -5
if [[ "$INT" = ~ ^-?[0-9]+$ ]]; then
echo "INT is an integer."
else
echo "INT is not an integer." >&2
fi

file=hello.sh
if [[ $file==hello.* ]]; then
echo "$file matches 'hello.*'"
fi

复合命令(( )),支持一套完整的算术计算,有利于操作整数(相比于上述的lt,可以使用<)

INT = -5
if (($INT<0)); then
echo "INT is negative"
else
echo "INT is positive"
fi

if判断条件支持使用逻辑运算符(也可以直接使用在命令行中,例如:command1 && command2
在这里插入图片描述

if [ ! \( $INT -ge $MIN_VAL -a $INT -le $MAX_VAL \) ]; then
   echo "$INT is outside $MIN_VAL to $MAX_VAL."
else
   echo "$INT is in range."
fi

test使用的所有的表达式和操作符都被shell看作是命令参数(不像对于bash有特殊含义的字符 [[ ]](( )) ),<>(、和 ),必须引起来或者是转义。

  • read读取键盘输入
    格式read [-options] [variable...]
    在这里插入图片描述
echo -n "please input variable > "  # -n使得echo完不换行,直接跟read输入
read variable
echo "the variable is $variable"

read -sp "please input passwd > " passwd  # -p:显示提示信息 -s:隐藏输入内容
echo "the passwd is $passwd"

read   # 如果read后面不加变量,shell变量REPLY会包含数据行
echo "REPLY = $REPLY"
  • df & du
    disk free(df):显示文件系统的可用空间和总空间;disk usage(du):显示已占用的磁盘空间
df -h  # df:查看系统空间容量 -h:“human-readable",它使输出的文件或目录大小以人类可读的格式显示,通常使用 KB、MB 或 GB 单位
du sh  # du:查看磁盘使用量  -h:同上;-s:summarize,显示文件的总大小
  • while until break continue
    类似于C和C++的语法
#!/bin/bash
# while break continue用法
DELAY=3 # Number of seconds to display results
while [[ $REPLY != 0 ]]; do
   clear
   cat << _EOF_
       Please Select:
       1. Display System Information
       2. Display Disk Space
       3. Display Home Space Utilization
       0. Quit
_EOF_
   read -p "Enter selection [0-3] > "
   if [[ $REPLY =~ ^[0-3]$ ]]; then
       if [[ $REPLY == 1 ]]; then
          echo "Hostname: $HOSTNAME"
           uptime
           sleep $DELAY
       continue
      fi
       if [[ $REPLY == 2 ]]; then
           df -h
          sleep $DELAY
     continue
       fi
       if [[ $REPLY == 3 ]]; then
           if [[ $(id -u) -eq 0 ]]; then
               echo "Home Space Utilization (All Users)"
               du -sh /home/*
           else
               echo "Home Space Utilization ($USER)"
               du -sh $HOME
           fi
           sleep $DELAY
       continue
       fi
   else
       echo "Invalid entry."
       sleep $DELAY
   break
   fi
done
echo "Program terminated."

# until语法
count=1
until [ $count -gt 5 ]; do
   echo $count
   count=$((count + 1))
done
echo "Finished."
  • case多选流程控制
# case语法
case 判断变量 in
   [pattern] | [pattern]...)   # 使用 | 实现或逻辑符功能
   commands 
   ;;
   # 如果是;;执行完case1退出,若是;;&执行完改case1会继续执行其他case?
   ...
esac
  • 位置参数
    $0表示已执行程序的路径名;$1-$9表示脚本后面所跟的参数;$#可以得到命令行参数的个数;shift执行一次 shift 命令,就会导致所有的位置参数 “向下移动一个位置”;$*$@会展开成一个从1开始的位置参数列表
  • for 循环
# for 有两种形式

# 1 把[in words]赋值给variable
for variable [in words]; do
   commands
done

# 2 类似于C语言
for (( expression1; expression2; expression3 )); do
   commands
done
  • 数组
    bash中的数组只支持单一维度;创建数组declare -a 数组名单值赋值name[subscript]=value(当被访问的时数组会被自动地创建),多值赋值name=(value1 value2 ...)输出单个元素echo ${array[1]}输出全部元素echo ${array[*]} 或 echo ${array[@]}输出数组元素个数echo ${#array[@]}输出某个元素的长度echo ${#array[1]};bash允许赋值的数组下标包含 “间隔”,输出有值元素的下标${!array[@]}在数组末尾添加元素array+=(d e f);排序array_sorted=($(for i in "${array[@]}"; do echo $i; done | sort))删除数组unset array关联数组,关联数组使用字符串而不是整数作为数组索引declare -A colors创建关联数组colors,colors["red"]="#ff0000" ;echo ${colors["red"]};任何没有下标的对数组变量的引用都指向数组元素0,array=0等价于array[0]=0.

原文地址:https://blog.csdn.net/qq_52757671/article/details/141277020

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!