shell
- 大概历时1个多月,一直在输入、琢磨有关linux-shell的鸡毛碎皮。单从目前来看收益甚微,因为大部分人的惯用做法是碰到不会的查一下,而不会专门的去学习。但从长远来看,我对shell有了宏观的了解,起码知道具体该查什么命令,而不是仅仅把问题的现象扔给度娘。下面推荐一个shell文档、一个命令行搜索工具、一个bash网站,这些都是师兄推荐、我用过并认为不错的。
- 接下来的时间,会向数学靠拢,具体学习方向是数理统计及机器人状态估计。
shell
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.gz
或gunzip 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的程序有egrep
和grep -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[换行] token
,command
是一个可以接受标准输入的命令名,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函数,把函数写入.bashrc
,source .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)!