Shell 脚本 — 多行注释、开启子/不开启子进程执行、转义带颜色输出、读取键盘输入、输入输出重定向、单双引号、命令替换、读取变量、系统变量、正则过滤、算术运算、一行多条命令、字符串比较
1. 多行注释
#!/bin/bash<< COMMENT
This is multi
line comment
COMMENTecho "This is demo script"
注意:
<<
符号后面的关键词可以是任意字符串,但是前面使用什么关键词,结束注释时必须使用同样的关键词,如果使用<< ABC
开始注释,那么结束注释时必须使用ABC
,字母区分大小写。
2. 执行方式
默认情况下,创建脚本之后是无法直接运行的:
$ ./demo.sh
-bash: ./demo.sh: Permission denied
但 bash
或者 sh
这样的解释器,是可以将脚本文件作为参数来执行脚本文件的。
$ bash demo.sh
This is demo script
$ sh demo.sh
This is demo script
修改脚本具有可执行权限,然后就可以使用相对路径或者绝对路径来执行了。
$ chmod +x demo.sh
$ ./demo.sh
This is demo script
$ /home/wohu/Downloads/shell_demo/demo.sh
This is demo script
$
2.1 开启子进程
输入 pstree
,可以看到
$ pstree
systemd─┬─ModemManager───2*[{ModemManager}]├─NetworkManager─┬─dhclient│ └─2*[{NetworkManager}]
...├─sshd─┬─2*[sshd───sshd───bash]│ ├─sshd───sshd───bash───pstree│ ├─sshd───sshd───sftp-server│ └─sshd───sshd───bash───ssh
...
可以看到系统启动的第一个进程是 systemd
,其它进程都是这个进程的子进程,不管是直接执行脚本,还是通过 bash
或者 sh
这样的解释器执行脚本,都是会开启子进程的,下面验证一下,
创建下面的文件内容并通过 ./sleep.sh
执行该脚本文件
$ cat sleep.sh
#!/bin/bash
sleep 100
然后输入 pstree
可以看到
├─sshd─┬─2*[sshd───sshd───bash]│ ├─sshd───sshd───bash───sleep.sh───sleep│ ├─2*[sshd───sshd───sftp-server]│ ├─sshd───sshd───bash───pstree│ └─sshd───sshd───bash───ssh
bash
终端下开启了一个子进程脚本文件 sleep.sh
,通过该脚本文件执行了一条 sleep
命令。
另外一种方法,使用 bash sleep.sh
执行,然后输入 pstree
可以看到
├─sshd─┬─2*[sshd───sshd───bash]│ ├─sshd───sshd───bash───bash───sleep│ ├─2*[sshd───sshd───sftp-server]│ ├─sshd───sshd───bash───pstree│ └─sshd───sshd───bash───ssh
bash
进程下开启了一个子进程 bash
,在 bash
子进程中执行了一条 sleep
命令。
2.2 不开启子进程
打开终端使用 source
或者 .
来执行脚本文件
$ source sleep.sh
或者
. sleep.sh
另外开个终端,然后输入 pstree
可以看到
├─sshd─┬─2*[sshd───sshd───bash]│ ├─sshd───sshd───bash───sleep│ ├─2*[sshd───sshd───sftp-server]│ ├─sshd───sshd───bash───pstree│ └─sshd───sshd───bash───ssh
脚本文件中的 sleep
命令是直接在 bash
终端下执行的。
特殊的文件命令如下
$ cat exit.sh
#!/bin/bash
exit
分别使用开启子进程和不开启子进程的方式执行,
$ source exit.sh
$ bash exit.sh
可以发现:
source
命令不开启子进程执行脚本文件会导致整个终端被关闭;bash
命令开启子进程执行脚本文件却不受影响;
3. 数据输入和输出
3.1 使用 echo 命令输出
echo
命令可以实现任意字符串消息的输出,可以使用多个 echo
输出多条消息,也可以使用一个 echo
命令,将多条信息用引号 ""
包含一起输出。
$ cat demo.sh
#!/bin/bashecho "one"
echo "two"
echo "This is
demo script"
echo
命令支持 -e
选项,该选项可以让 echo
命令识别 \
后面的转义符含义,常见的转义符见下表:
注意:
-e
选项和后面的输出内容至少要有一个空格。
echo -e "\033[1mok\033[0m"
\033
或者 \e
后面跟不同的代码可以设置不同的终端属性,如 1m
是让终端粗体显示字符串、后面的 OK
就是需要显示的字符串内容,最后的 \033[0m
是在终端加粗显示字符串后,关闭终端的属性设置,如果没有使用 0m
关闭属性设置,则之后终端所有字符串都用粗体显示。
使用示例:
#!/bin/bash
#Version:2.0
clear
echo -e "\033[42m---------------------------------\033[0m"
echo -e "\e[2;10H这里是菜单\t\t#"
echo -e "#\e[32m 1.查看网卡信息\e[0m #"
echo -e "#\e[33m 2.查看内存信息\e[0m #"
echo -e "#\e[34m 3.查看磁盘信息\e[0m #"
echo -e "#\e[35m 4.查看CPU信息\e[0m #"
echo -e "#\e[36m 5.查看账户信息\e[0m #"
echo -e "\033[42m---------------------------------\033[0m"
echo
3.2 使用 read 命令读取
read
命令语法如下:
read [选项] [变量名]
如果未指定变量名,则变量名默认为 REPLY
。
4. 输入输出重定向
Linux 系统输出可以分为标准输出和标准错误输出。
- 标准输出的文件描述符为
1
- 标准错误输出的文件描述符为
2
- 标准输入的文件描述符为
0
可以使用 > 或者 >> 符号将输出信息重定向到文件中。
- > 符号将输出信息重定向到文件,如果文件不存在,则系统会自动创建该文件,如果文件已经存在,则系统会将文件的所有内容覆盖;
- >> 符号将输出信息重定向到文件,如果文件不存在,则系统会自动创建该文件,如果文件已经存在,则系统会将输出的信息追加到该文件原有信息的末尾;
使用 1 > 或者 1 >> 可以将标准输出信息重定向到文件 (1 可以忽略不写,默认值就是 1)。可以使用 2 > 或者 2 >> 将错误的输出信息重定向到该文件。
使用 <<
符号可以将数据内容重定向传递给前面的一个命令,作为命令的输入。<<
符号代表需要的内容在这里。
[wohu@bogon Videos]$ cat > demo.sh << EOF
this is demo
EOF
[wohu@bogon Videos]$ cat demo.sh
this is demo
[wohu@bogon Videos]$
[wohu@bogon Videos]$ cat > demo.sh << HERE
this is test script
HERE
[wohu@bogon Videos]$ cat demo.sh
this is test script
[wohu@bogon Videos]$
5. 各种引号的使用
5.1 单双引号
$ touch a b c # 创建三个文件,分别为 a b c
$ touch "a b c" # 创建一个文件,空格为文件名的一部分
双引号的作用是引用一个整体,计算机会把整个引号内的内容当做一个整体来看待。
在 Linux
系统中,除了可以使用一个双引号引用一个整体,也可以使用单引号引用一个整体,同时单引号还有另外一个功能是将特殊字符含义屏蔽,转化为字符表面的含义。
$ touch 'a b c'
$ echo ############
本来想输出一个 #
符号,但实际输出的是一个空白行,因为 #
符号及其后面的内容会被理解为注释而不会执行,所以要想输出 #
符号,可以使用单引号 '###'
。
$ echo '########'
Shell
中 $
符号具有提取变量值的特殊含义,当需要显示 $
符号时,也需要使用单引号屏蔽功能。
wohu@wohu-pc:~$ test=19
wohu@wohu-pc:~$ echo "$test"
19
wohu@wohu-pc:~$ echo '$test'
$test
wohu@wohu-pc:~$
5.2 命令替换
反引号 ` 是一个命令替换符号,它可以使用命令的替换结果替代命令。
wohu@wohu-pc:~$ echo `date +%Y-%m-%d`
2022-07-27
wohu@wohu-pc:~$
wohu@wohu-pc:~$ echo `ls | wc -l`
16
wohu@wohu-pc:~$
反引号容易跟单引号混淆,并且不支持嵌套,所以又有了 $()
组合命令,同样用于命令替换。
wohu@wohu-pc:~$ echo $(pwd)
/home/weirong
wohu@wohu-pc:~$ echo $(ls | wc -l)
16
wohu@wohu-pc:~$ echo $(date +%Y-%m-%d)
2022-07-27
wohu@wohu-pc:~$
6. 变量
变量名由数字、字母、下划线组成,且开头不能以数字开头,定义变量时等号两边不可以有空格。
当需要读取变量时,需要在变量名前加一个 $
符号,且变量名与其它非变量名混在一起时,需要使用 {}
分隔。
wohu@wohu-pc:~$ a = 123
a: command not found
wohu@wohu-pc:~$ a=123
wohu@wohu-pc:~$ echo $a
123
wohu@wohu-pc:~$ echo $(a) # $() 用于命令替换
a: command not foundwohu@wohu-pc:~$ echo ${a} # ${} 用于引用变量
123
wohu@wohu-pc:~$ echo $aappleswohu@wohu-pc:~$ echo ${a}apples
123apples
wohu@wohu-pc:~$
脚本
#!/bin/bash
#描述信息:本脚本主要目的是获取主机的数据信息(内存、网卡IP、CPU负载)localip=$(ifconfig eth0 | grep netmask | tr -s " " | cut -d" " -f3)
mem=$(free |grep Mem |tr -s " " | cut -d" " -f7)
cpu=$(uptime | tr -s " " | cut -d" " -f13)
echo "本机IP地址是:$localip"
echo "本机内存剩余容量为:$mem"
echo "本机CPU 15分钟的平均负载为:$cpu"
tr -s " "
将多个空格合并为一个cut -d" " -f3
以空格分列,并输出第三列
常见系统预设变量有:
7. 数据过滤与正则表达
grep [选项] 匹配模式 [文件]
-i
忽略字母大小写-v
取反匹配-w
匹配单词
8. 算术运算
Shell
支持多种算术运算,可以使用 $((表达式))
、$[表达式]
、let 表达式
进行整数算术运算,使用 bc 命令进行小数运算。
wohu@wohu-pc:~$ echo $((3+4))
7
wohu@wohu-pc:~$ echo $[3+4]
7
wohu@wohu-pc:~$ a=3
wohu@wohu-pc:~$ echo $[a++]
3
wohu@wohu-pc:~$ echo $[a++]
4
wohu@wohu-pc:~$ echo $[++a]
6
wohu@wohu-pc:~$
运算符号见下表:
9. 一行多条命令
一行代码中输入多行 shell
命令,可以用分号 ;
,与号 &&
,或 ||
将多个命令分开。
cmd1 ; cmd2
先执行cmd1
,再执行cmd2
,不管cmd1
执行结果如何,整个命令的退出码以cmd2
为准;cmd1 && cmd2
仅当cmd1
执行成功后,才会执行cmd2
,两条命令都执行成功,则整行命令的退出码为 0,有任意一个执行失败,整行命令的退出码为非 0;cmd1 || cmd2
一般很少用,只有当cmd1
不执行或者执行失败时才会执行cmd2
,cmd1
和cmd2
是二选一的关系,两个中的任意一个执行成功,那么整条命令的退出码为 0,否则返回非 0;
10. 字符串比较
wohu@ubuntu:~$ test a == a
wohu@ubuntu:~$ echo $?
0
wohu@ubuntu:~$ test a == b; echo $?
1
wohu@ubuntu:~$ [ $USER == wohu ] && echo Y || echo N
Y
wohu@ubuntu:~$ [ $USER != wohu ] && echo Y || echo N
N
wohu@ubuntu:~$
表达式 -z
测试字符串是否为空。
wohu@ubuntu:~$ a=123
wohu@ubuntu:~$ [ -z $a ] && echo Y || echo N
N
wohu@ubuntu:~$ [ -z $b ] && echo Y || echo N
Y
wohu@ubuntu:~$
在 Shell
中进行条件测试时一定要注意空格问题,使用 []
测试时,左括号右边和右括号左边都必须要有空格,而且测试的比较符号两边也必须都有空格。
wohu@ubuntu:~$ [a == city] # 前后都缺少空格,报错
[a: command not found
wohu@ubuntu:~$
下面的例子,==
符号两边都没有空格,无论怎么测试结果都为真,编写脚本时这种 Bug
系统不会提示语法错误,但是程序结果有可能是错误的。
wohu@ubuntu:~$ [ a==city ]; echo $? # 退出码是错误的
0
wohu@ubuntu:~$ [ a == city ]; echo $?
1
wohu@ubuntu:~$
还可以使用 -n
测试一个字符串是否为非空,在实际应用时最好将测试对象使用双引号引起来。否则当测试一个未定义的变量时就会出现下面的问题。
wohu@ubuntu:~$ [ -n $str ]; echo $?
0
wohu@ubuntu:~$
因为当 $str
为空时,等同于执行了下面的第一条命令,是在测试一个空格是否为空值。而计算机理解空格也是有值的,并非没有值(空值),所以这样的测试结果总为真。
wohu@ubuntu:~$ [ -n ] && echo Y || echo N
Y
wohu@ubuntu:~$
为了避免这样的错误,可以使用双引号将变量引起来。
wohu@ubuntu:~$ [ -n "$str" ]; echo $?
1
wohu@ubuntu:~$ [ -n "$str"] && echo Y || echo N # 右方括号前没有空格,导致结果错误,切记
Y
wohu@ubuntu:~$ [ -n "$str" ] && echo Y || echo N
N
wohu@ubuntu:~$
Shell 脚本 — 多行注释、开启子/不开启子进程执行、转义带颜色输出、读取键盘输入、输入输出重定向、单双引号、命令替换、读取变量、系统变量、正则过滤、算术运算、一行多条命令、字符串比较相关推荐
- 【shell】实现交互|read读取键盘输入
目录 一.SHELL 1.1 输入单个指令 1.2 输入多行指令 限制输入内容的个数 控制输入内容的可见性 二.Expect 简介 for 中嵌套 expect 在expect中使用shell的环境变 ...
- 编写shell脚步--读取键盘输入
文章目录 一.read--从标准输入读取输入值 1.1.选项 1.2.使用IFS间隔输入字段 二.验证输入 三.菜单 一.read–从标准输入读取输入值 内嵌命令read的作用是读取一行标准输入.此命 ...
- Linux下sed命令替换配置文件中某个变量的值(改变包含字符的一行的值)之二——只改变第一出现的那一行
一.背景 在之前的文章中有介绍过<Linux下sed命令替换配置文件中某个变量的值(改变包含字符的一行的值)> 但是这种方法存在一定的问题,就是假如某个变量在一个文件中出现两次,却只想更改 ...
- DM8联机逻辑备份perl脚本实现要点(单双引号、system和disql)
概要 此文章非完整脚本功能分享,仅就实现逻辑备份功能进行分享. 问题背景 在编写DM8自动化备份perl脚本中,在涉及联机物理库级备份时,需要执行相关操作,正常情况下,相应语句如下(已简写,便于理解) ...
- python 输出引号_python输出字符串单双引号如何选择
在Python当中字符串的输出既可以使用单引号,也可以使用双引号,使用单引号或双引号是没有区别的:当使用双引号将输出的字符串括起来时,内部也可使用单引号,将单双引号匹配正确即可. 在Python中我们 ...
- linux如何过滤字符串,在linux系统如何grep过滤中,不包含某些字符串的命令
转:http://www.dutycode.com/linux_grep_bubaohan.html 文章系转载,亲测可用(转载自:http://www.itokit.com/2014/0105/75 ...
- python 并发执行命令_python: 多线程实现的两种方式及让多条命令并发执行
一 概念介绍 Thread 是threading模块中最重要的类之一,可以使用它来创建线程.有两种方式来创建线程:一种是通过继承Thread类,重写它的run方法:另一种是创建一个threading. ...
- python中执行shell脚本之subprocess模块,python用subprocess执行shell脚本
用subprocess中的Popen() 方法来得到shell脚本的一些运行结果,并且也可以指定不同的shell内核. 其构造函数为: class subprocess.Popen(args, buf ...
- linux shell 引号 参数,shell(三)变量,基本语法,单双引号
shell中的变量 变量的声明:在shell中变量不需要事先声明,不必显示声明 变量的赋值:VAR=value,不允许有空格.如:a=100 变量的数据类型:shell中的变量无数据(弱)类型!同一变 ...
最新文章
- BigMemroy系列文章--11. BigMemory中的SizeOf问题
- 2.4带通采样的实际问题
- tp剩余未验证内容-7
- 23种设计模式C++源码与UML实现--访问者模式
- YbtOJ#20067-[NOIP2020模拟赛B组Day5]糖果分配【dp】
- 七月老师python_七月在线Python学习笔记
- 【codevs1565】【BZOJ2242】计算器,数论练习
- PDF文件分割电脑版怎么操作
- 【路径规划】基于matlab A_star算法机器人走迷宫路径规划【含Matlab源码 1389期】
- 半监督学习和直推式学习
- java中文转英文_eclipse英文转中文怎么设置 eclipse中英文切换图文教程
- EasyExcel3.0.5 解决大数据导入导出,防止OOM
- html弹窗后 自动关闭页面,网页一键复制弹出提示窗口后几秒后自动关闭提示js代码...
- sprint 1 总结
- 显卡测试软件毛毛虫,ATI Radeon Xpress200M与Intel GMA950谁强些?
- nginx: [warn] conflicting server name 这里是域名 eg:abc.com on 0.0.0.0:80, ignored解决方法
- 【JQuery】关于jQuery的load方法在Laravel里的使用
- 华为思科宣布全力布局,美国NSF巨资支持的NDN到底什么来头?
- 注册苹果开发者帐号 用什么银行的什么卡好? 收款帐号呢?
- 二、执行v8引擎示例代码