Shell 脚本语言是实现 Linux/UNIX 系统管理及自动化运维所必备的重要工具, Linux/UNIX 系统的底层及基础应用软件的核心大都涉及 Shell 脚本的内容。每个合格 的Linux 系统管理员或运维工程师,都须要可以熟练地编写 Shell 脚本语言,并可以阅读系统及各种软件附带的 Shell 脚本内容。只有这样才能提高运维人员的工做效率,适 应曰益复杂的工做环境,减小没必要要的重复工做,从而为我的的职场发展奠基较好的基础php
Shell 是一个命令解释器,它在操做系统的最外层,负责直接与用户对话,把用户的输入解释给操做系统,并处理各类各样的操做系统的输出结果,输出屏幕返回给用户。
html
这种对话方式能够是:前端
[root@mico ~]# echo "hello" hello [root@mico ~]# pwd /root [root@mico ~]#
定义:指用专用的编译器,针对特定的操做平台(操做系统)将某种高级语言源代码一次性翻译成可被硬件平台直接运行的二进制机器码(具备操做数,指令、及相应的格式),这个过程叫作编译(./configure make makeinstall );编译好的可执行性文件(.exe),可在相对应的平台上运行(移植性差,但运行效率高)。典型的编译型语言有, C语言、C++等。另外,Java语言是一门很特殊的语言,Java程序须要进行编译步骤,但并不会生成特定平台的二进制机器码,它编译后生成的是一种与平台无关的字节码文件(*.class)(移植性好的缘由),这种字节码天然不能被平台直接执行,运行时须要由解释器解释成相应平台的二进制机器码文件;大多数人认为Java是一种编译型语言,但咱们说Java便是编译型语言,也是解释型语言也并无错。
定义:指用专门解释器对源程序逐行解释成特定平台的机器码并当即执行的语言;至关于把编译型语言的编译连接过程混到一块儿同时完成的。解释型语言执行效率较低,且不能脱离解释器运行,但它的跨平台型比较容易,只需提供特定解释器便可。常见的解释型语言有, Python(同时是脚本语言)与Ruby等。
定义:为了缩短传统的编写-编译-连接-运行(edit-compile-link-run)过程而建立的计算机编程语言。 特色:程序代码便是最终的执行文件,只是这个过程须要解释器的参与,因此说脚本语言与解释型语言有很大的联系。脚本语言一般是被解释执行的,并且程序是文本文件。
典型的脚本语言有,JavaScript,Python,shell等。java
shell 脚本的优点在于处理操做系统底层的业务 (linux 系统内部的应用都是 shell 脚本完成)由于有大量的 linux 系统命令为它作支撑。2000 多个命令都是 shell 脚本编程的有力支撑,特别是grep、awk、sed 等。例如:一键软件安装、优化、监控报警脚本,常规的业务应用,shell 开发更简单快速,符合运维的简单、易用、高效原则。PHP、Python 优点在于开发运维工具以及 web 界面的管理工具,web 业务的开发等。处理一键软件安装、优化,报警脚本。常规业务的应用等 php/python 也是可以作到的。可是开发效率和复杂比用 shell 就差不少了。python
[root@mico ~]# cat /etc/redhat-release CentOS Linux release 7.5.1804 (Core) [root@mico ~]# uname -r 3.10.0-862.11.6.el7.x86_64 [root@mico ~]# getenforce Disabled [root@mico ~]# systemctl status firewalld.service ● firewalld.service - firewalld - dynamic firewall daemon Loaded: loaded (/usr/lib/systemd/system/firewalld.service; disabled; vendor preset: enabled) Active: inactive (dead) Docs: man:firewalld(1) [root@mico ~]#
[root@mico ~]# cat /etc/shells /bin/sh /bin/bash /sbin/nologin /usr/bin/sh /usr/bin/bash /usr/sbin/nologin /bin/tcsh /bin/csh [root@mico ~]#
[root@mico ~]# echo $SHELL /bin/bash
[root@VM_42_34_centos /]# head -1 /etc/init.d/network #! /bin/bash [root@VM_42_34_centos /]# head -1 /etc/init.d/netconsole #!/bin/bash
[root@mico ~]# bash -version GNU bash, 版本 4.2.46(2)-release (x86_64-redhat-linux-gnu) Copyright (C) 2011 Free Software Foundation, Inc. 许可证 GPLv3+: GNU GPL 许可证版本3或者更高 <http://gnu.org/licenses/gpl.html> 这是自由软件,您能够自由地更改和从新发布。 在法律容许的范围内没有担保.
使用 命令 env x='() { :;}; echo be careful' bash -c "echo this is a test"
若是返回结果为一行,则为正常,linux
[root@mico ~]# env x='() { :;}; echo be careful' bash -c "echo this is a test" this is a test #解决办法 升级当前的bash版本 yum install update bash
早期的bash和sh稍有不一样,还包含了csh和ksh的特点,但大多数脚本均可以不加修改地在sh上运行web
[root@VM_42_34_centos ~]# ll /bin/bash -rwxr-xr-x 1 root root 964544 4月 11 2018 /bin/bash [root@VM_42_34_centos ~]# ll /bin/sh lrwxrwxrwx 1 root root 4 8月 10 2018 /bin/sh -> bash
说明:sh为bash的软连接,通常状况下,脚本开头使用“#!/bin/bash”和"#!/bin/sh"是没有区别的,但更规范的写法是在脚本开头使用“#!/bin/bash”
下面的Shell脚本是系统自带的软件启动脚本的开头部分面试
[root@mico ~]# ll /bin/sh lrwxrwxrwx 1 root root 4 8月 10 2018 /bin/sh -> bash
[root@mico ~]# ll /bin -d lrwxrwxrwx 1 root root 7 8月 10 2018 /bin -> usr/bin
[root@mico ~]# mkdir -p /server/scripts/ [root@mico ~]# cd /server/scripts/
脚本第一行指出由哪一个程序(解释器)来执行脚本中的内容
#!/bin/bash
或#!/bin/sh
(255个字符之内)shell
注意格式 ↓
其中开头的"#!"字符又称为幻数,在执行bash脚本的时候,内核会根据"#!"后的解释器来肯定该用那个程序解释这个脚本中的内容。编程
[root@mico scripts]# head -1 /etc/init.d/* ==> /etc/init.d/functions <== # -*-Shell-script-*- ==> /etc/init.d/netconsole <== #!/bin/bash ==> /etc/init.d/network <== #! /bin/bash ==> /etc/init.d/README <== You are looking for the traditional init scripts in /etc/rc.d/init.d,
使用 .vimrc
文件,将下面的信息添加到 .vimrc
文件中,可以快速的生成开头的注释信息
autocmd BufNewFile *.py,*.cc,*.sh,*.java exec ":call SetTitle()" func SetTitle() if expand("%:e") == 'sh' call setline(1,"#!/bin/bash") call setline(2, "##############################################################") call setline(3, "# File Name: ".expand("%")) call setline(4, "# Version: V1.0") call setline(5, "# Author: mico") call setline(6, "# Created Time : ".strftime("%F %T")) call setline(7, "# Description:") call setline(8, "##############################################################") call setline(9, "") endif endfunc
使用后的效果
#!/bin/bash ############################################################## # File Name: scripts_tmp.sh # Version: V1.0 # Author: mico # Created Time : 2019-07-09 10:12:27 # Description: ##############################################################
在Shell脚本中,跟在#
后面的内容表示注释。注释部分不会被执行,仅给人看。注释能够自成一行,也能够跟在命令后面,与命令同行。要养成写注释的习惯,方便本身与他人。
最好不用中文注释,由于在不一样字符集的系统会出现乱码。(字符集为zh_CN.UTF-8,为中文)。
名字要有意义,而且结尾以 .sh
结束(并非必须)
.sh
为扩展名~/.vimrc
文件自动添加。[ ]
、' '
、" "
等[ ]
两端要有空格,先输入[ ]
,退格,输入 2 个空格,再退格写。if 条件 ; then 内容;fi
)当 Shell 脚本运行时,会先查找系统环境变量 ENV,该变量指定了环境文件(加载顺序一般是 /etc/profile
、~/.bash_profile
、~/.bashrc
、/etc/bashrc
),在加载了上述变量文件后,Shell就开始执行脚本中的内容。
Shell 脚本是从上至下、从左至右依次执行每一行的命令及语句的。即执行完了一个命令后再执行下一个,若是在 Shell 脚本中(即脚本嵌套)
时,就会先执行子脚本的内容,完成后再返回父脚本继续执行父脚本内后序的命令及语句。
一般状况下,在执行 Shell 脚本时,会向系统内核请求启动一个新进程,以便在该进程或只能怪执行脚本的命令以及子Shell 脚本。
(1)sh/bash scripts.sh
当脚本自己没有可执行权限时使用的方法,或脚本文件开头没有指定解释器时须要使用分方法。
(2)首先chown +x
,而后./scripts.sh
或 .path/scripts.sh
在当前路径下执行脚本(脚本须要有执行权限),经过绝对路径或相对路径直接执行脚本
(3)source scripts.sh
或 . (空格) scripts.sh
这种方法一般是使用 source
或 .
读入或加载指定的 shell 脚本文件(不须要执行权限),而后依次执行指定 shell 脚本中的全部语句。这些语句将在当前 shell 脚本的进程中运行(其余几种模式都会启动新的进程执行子脚本)。source
或 .
命令的功能是在当前 Shell 中执行 source
或 .
加载并执行的相关脚本文件中的命令及语句,而不是产生一个子 Shell 来执行文件中的命令。
说明:.
或 source
命令的功能相同,都是读入脚本并执行脚本中的命令。
(4)sh < script-name 或 cat scripts-name|sh 效率低
一样适用于bash,不过这种用法不常见。
soucre命令
[root@mico ~]# help source |head -2 source: source 文件名 [参数] 在当前 shell 中执行一个文件中的命令。 . (点) [root@mico ~]# help . |head -2 .: . 文件名 [参数] 在当前 shell 中执行一个文件中的命令。
对比:用 source 执行脚本文件,执行过程不另开进程,脚本文件中设定的变量在当前shell中能够看到;
用 sh/bash 执行脚本文件,是在当前进程另开子进程来执行脚本命令,脚本文件中设定的变量在当前shell中不能看到。
例如
[root@VM_42_34_centos trsky]# echo 'userdir=`pwd`' >> testsource.sh [root@VM_42_34_centos trsky]# cat testsource.sh userdir=`pwd` [root@VM_42_34_centos trsky]# sh testsource.sh [root@VM_42_34_centos trsky]# echo $userdir [root@VM_42_34_centos trsky]# source testsource.sh [root@VM_42_34_centos trsky]# echo $userdir /home/trsky [root@VM_42_34_centos trsky]#
由案例可知,使用 source
或 .
执行的脚本中的变量值会传递到当前的 Shell 下,由于使用 source
或 .
执行脚本不会开启新的进程,而是在统一进程下完成脚本中全部指令的执行。
[root@mico scripts]# sh mico_test.sh Hello World! [root@mico ~]# echo $Mico Mico # sh 新建一个Shell窗口(新建一个进程)执行一个文件中的命令。 [root@mico scripts]# source mico_test.sh Hello World! [root@mico scripts]# echo $mico Hello World!
问 sh test.sh 后 echo $user 返回的结果__空_ ?
[root@oldboy scripts]# cat test.sh #!/bin/bash user=`whoami`
Shell为弱类型语言,因此在默认状况下,在Bash Shell中是不会区分变量类型的。但Shell能够通 declare 显示定义变量的类型。
变量能够分为两类:环境变量(全局变量)和普通变量(局部变量)
Shell中定义变量名以及为变量内容赋值要求
变量名通常由字母、数字、下划线组成,能够由字母或下划线开头
把一个命令的结果做为变量的内容赋值的方法
ls
使用 env/declare/set/export -p
命令查看系统中的环境变量,这三个命令的的输出方式稍有不一样。
[root@mico scripts]# env XDG_SESSION_ID=1 HOSTNAME=mico TERM=linux SHELL=/bin/bash HISTSIZE=1000 SSH_CLIENT=10.0.0.1 5537 22 SSH_TTY=/dev/pts/0 USER=root ~~~
[root@mico ~]# echo $LANG zh_CN.UTF-8
设置环境变量
export
和 declare
[root@VM_42_34_centos ~]# cat /etc/profile|grep Mico export Mico='mico' [root@VM_42_34_centos ~]# source /etc/profile [root@VM_42_34_centos ~]# echo $MIco [root@VM_42_34_centos ~]# echo $Mico mico [root@VM_42_34_centos ~]# env|grep Mico Mico=mico [root@VM_42_34_centos ~]#
# 用户的环境变量设置,比较常见的是用户家目录下的.bashrc 和 .bash_profile [root@mico ~]# ls /root/.bashrc /root/.bashrc [root@mico ~]# ls /root/.bash_profile /root/.bash_profile [root@mico ~]#
/etc/profile /etc/bashrc /etc/profile.d/
若是要在登录后初始化或显示加载内容,则将脚本文件放在/etc/profile.d/下便可(无需执行权限)
/etc/motd
里增长提示的字符串[root@mico ~]# vim /etc/motd [root@mico ~]# cat /etc/motd Welcome to Linux.
/etc/profile.d/
目录下添加脚本[root@mico profile.d]# cat /etc/profile.d/mico.sh #!/bin/bash ############################################################## # File Name: /etc/profile.d/mico.sh # Version: V1.0 # Author: mico # Created Time : 2019-07-01 10:00:06 # Description: ############################################################## echo "Hello, you are studing Linux"
登陆后出现
Connection established. To escape to local shell, press 'Ctrl+Alt+]'. Welcome to Linux. Hello, you are studing Linux [root@mico ~]#
#常见的系统环境变量 $HOME:用户登陆时进入的目录 $UID:当前用户的UID(用户标识),至关于 id-u $PWD:当前工做目录的绝对路径名 $SHELL:当前Shell $USER:当前yonghu ... 打印或删除环境变量 #打印环境 printf "$Home\n" echo $PWD
#删除环境变量 unset PWD
本地变量在用户当前的Shell生存期的脚本中使用。例如,本地变量OLDBOY取值为bingbing,这个值在用户当前Shell生存期中有意义。若是在Shell中启动另外一个进程或退出,本地变量值将无效
变量名=value //解释变量名 变量名='value' //不解释变量名 变量名="value" //解释变量名
[root@mico ~]# a=1 [root@mico ~]# b='2' [root@mico ~]# c="3" [root@mico ~]# echo "$a" 1 [root@mico ~]# echo "$b" 2 [root@mico ~]# echo "${c}"
提示:$变量名表示输出变量,能够用$c和${c}两种用法
【小结】连续普通字符串内容赋值给变量,无论用什么引号或者不用引号,它的内容是什么,打印变量就输出什么
[root@mico ~]# help export export: export [-fn] [名称[=值] ...] 或 export -p 为 shell 变量设定导出属性。
标记每一个 NAME 名称为自动导出到后续命令执行的环境。若是提供了 VALUE
则导出前将 VALUE 做为赋值。
定义变量
[root@mico scripts]# CSLN=mico [root@mico scripts]# export CSLN1=1 # 当前窗口查看 [root@mico scripts]# echo $CSLN mico [root@mico scripts]# echo $CSLN1 1 # 编写测试脚本 [root@mico scripts]# vim quanju.sh #!/bin/bash echo $CSLN echo $CSLN1 # 使用sh执行 [root@mico scripts]# sh quanju.sh 1 # 使用source 执行 [root@mico scripts]# source quanju.sh mico 1
① /etc/profile
② ~/.bash_profile
③ ~/.bashrc
④ /etc/bashrc
1) 经过系统用户登录后默认运行的shell
2) 非登陆交互式运行Shell
3) 执行脚本运行非交互式Shell
文件读取过程示意图
验证四文件读取顺序的方法
sed -i '1a echo "$(date +%T-%s) /etc/profile1" >>/tmp/mico' /etc/profile sed -i '$a echo "$(date +%T-%s) /etc/profile2" >>/tmp/mico' /etc/profile sed -i '1a echo "$(date +%T-%s) /etc/bashrc1" >>/tmp/mico' /etc/bashrc sed -i '$a echo "$(date +%T-%s) /etc/bashrc2" >>/tmp/mico' /etc/bashrc sed -i '1a echo "$(date +%T-%s) ~/.bashrc1" >>/tmp/mico' ~/.bashrc sed -i '$a echo "$(date +%T-%s) ~/.bashrc2" >>/tmp/mico' ~/.bashrc sed -i '1a echo "$(date +%T-%s) ~/.bash_profile1" >>/tmp/mico' ~/.bash_profile sed -i '$a echo "$(date +%T-%s) ~/.bash_profile2" >>/tmp/mico' ~/.bash_profile
环境变量通常是指用export内置命令导出的变量,用户定义shell的运行环境。保证shell命令的正确执行。Shell经过环境变量来肯定登陆用户名、命令路径、终端类型、登陆目录等。若是须要永久保存环境变量,可在用户家目录下的.bash_profile或.bashrc(非用户登陆模式特有,例如远程登陆SSH)文件中,或者全局配置/etc/bashrc(非用户登陆模式特有,如远程SSH)或/etc/profile文件中定义。在将环境变量放入上述的文件以后,每次用户登陆时这些变量将被初始化。
[root@mico ~]# name=vicodona [root@mico ~]# name2='mico' [root@mico ~]# name3="you are my heart" [root@mico ~]# echo $name vicodona [root@mico ~]# echo $name2 mico [root@mico ~]# echo $name3 you are my heart [root@mico ~]# name4='mi co' [root@mico ~]# echo $name4 mi co [root@mico ~]# name5="mi co" [root@mico ~]# echo $name5 mi co [root@mico ~]# name6="mico $PWD" [root@mico ~]# echo $name6 mico /root [root@mico ~]# name6='mi co $PWD' [root@mico ~]# echo $name6 mi co $PWD [root@mico ~]# name7="mico $PWD" [root@mico ~]# echo $name7 mico /root
a.MicoAge=22 b.NETWORKING=yes
a.NFSD_MODULE="no load" b.MyName="Oldboy is a handsome boy."
a.OLDBOY_NAME='OLDBOY'
[root@mico scripts]# time=`date` [root@mico scripts]# echo $time 2017年 12月 05日 星期二 09:02:06 CST [root@mico scripts]# file=`ls` [root@mico scripts]# echo $file mico_test.sh panduan.sh quanju.sh yhk.sh
打印变量的时候防止出现“金庸新著”的问题
[root@mico ~]# time=`date` [root@mico ~]# echo $time 2019年 07月 18日 星期四 17:47:23 CST [root@mico ~]# echo ${time}_day 2019年 07月 18日 星期四 17:47:23 CST_day [root@mico ~]# echo $time-day 2019年 07月 18日 星期四 17:47:23 CST-day
# 使用脚本测试 [root@mico ~]# vim variable.sh #!/bin/bash time=`date` echo $timeday echo ${time}day [root@mico ~]# sh variable.sh 2019年 07月 18日 星期四 17:49:51 CSTday
名称 | 解释 |
---|---|
单引号 | 所见即所得,即输出时会将单引号内的全部内容都原样输出,或者描述为单引号里面看到的是什么就会输出什么;这称为强引用 |
双引号(默认) | 输出双引号内的全部内容;若是内容中有命令、变量、特殊字符等,会先把变量、命令、转义字符解析出结果,而后再输出最终内容,推荐使用,称为弱引用 |
无引号 | 赋值时,若是变量内容中有空格,则会形成赋值不完整。而在输出内容时,会将含有空格的字符串视为一个总体来输出;若是内容中有命令、变量等,则会先把变量、命令解析出结果,而后输出最终内容;若是字符串中带有空格等特殊字符,则有可能没法完整的输出,所以须要改加双引号 |
反引号 | 通常用于引用命令,执行的时候命令会被执行,至关于`$()`,赋值和输出都要用 命令引发来 |
示例:
MicoAge=22 #<==每一个单词的首字母大写的写法 mico_age=22 #<==单词之间用"_"的写法 micoAgeSex=man #<==驼峰语法:首个单词的首字母小写,其他单词首字母大写 MICOAGE=22 #<==单词全大写的写法
经常使用的特殊位置参数说明
位置变量 | 做用说明 |
---|---|
$0 | 获取当前执行的shell脚本的文件名,若是执行脚本带路径那么就包括脚本路径。 |
$n | 获取当前执行的shell脚本的第n个参数值,n=1..9,当n为0时表示脚本的文件名,若是n大于9用大括号括起来{10},参数以空格隔开。 |
$# | 获取当前执行的shell脚本后面接的参数的总个数 |
$* | 获取当前shell的全部传参的参数,不加引号同$@;若是给$加上双引号,例如: “$”,则表示将全部的参数视为单个字符串,至关于“112$3”。 |
$@ | 获取当前shell的全部传参的参数,不加引号同$*;若是给$@加上双引号,例如: “$@”,则表示将全部参数视为不一样的独立字符串,至关于“$1” “$2” “$3” “……”,这是将参数传递给其余程序的最佳方式,由于他会保留全部内嵌在每一个参数里的任何空白。 |
当$*
和$@
都加双引号时,二者有区别,都不加双引号时,二者无区别。
举例说:
脚本名称叫 test.sh 入参三个: 1 2 3
运行 test.sh 1 2 3后
$* 为 "1 2 3"(一块儿被引号包住)
$@ 为 "1" "2" "3"(分别被包住)
[root@mico ~]# vim parameter.sh #!/bin/bash echo $0 echo "第一个参数:" $1 echo "第二个参数:" $2 echo "第11个参数:" ${11} [root@mico ~]# sh parameter.sh parameter.sh 第一个参数: 第二个参数: 第11个参数: [root@mico ~]# [root@mico ~]# sh parameter.sh 1 2 3 4 5 6 7 8 9 10 11 parameter.sh 第一个参数: 1 第二个参数: 2 第11个参数: 11 [root@mico ~]#
[root@mico ~]# cat parameter.sh #!/bin/bash ############################################################## # File Name: parameter.sh # Version: V1.0 # Author: mico # Created Time : 2019-07-18 17:50:45 # Description: ############################################################## echo $0 echo "第一个参数:" $1 echo "第二个参数:" $2 echo "第10个参数:" ${10} echo "第11个参数:" ${11} echo "参数个数:" $# [root@mico ~]# sh parameter.sh 1 2 3 4 5 6 7 8 9 10 11 parameter.sh 第一个参数: 1 第二个参数: 2 第10个参数: 10 第11个参数: 11 参数个数: 11
[root@mico ~]# vim parameter.sh #!/bin/bash ############################################################## # File Name: parameter.sh # Version: V1.0 # Author: mico # Created Time : 2019-07-18 17:50:45 # Description: ############################################################## echo $0 echo "第一个参数:" $1 echo "第二个参数:" $2 echo "第10个参数:" ${10} echo "第11个参数:" ${11} echo "参数个数:" $# echo "参数:"$* [root@mico ~]# sh parameter.sh 1 2 3 4 5 6 7 8 9 10 11 parameter.sh 第一个参数: 1 第二个参数: 2 第10个参数: 10 第11个参数: 11 参数个数: 11 参数:1 2 3 4 5 6 7 8 9 10 11
$*
与$@
对比实践[root@mico scripts]# set -- "I am" handsome boy.. [root@mico scripts]# echo $1 I am [root@mico scripts]# echo $2 handsome [root@mico scripts]# echo $3 boy.. [root@mico scripts]# echo $* I am handsome boy.. [root@mico scripts]# echo $@ I am handsome boy.. [root@mico scripts]# for i in $*;do echo $i ;done I am handsome boy.. [root@mico scripts]# for i in $@;do echo $i ;done I am handsome boy.. [root@mico scripts]# for i in "$@";do echo $i ;done I am handsome boy.. [root@mico scripts]# for i in "$*";do echo $i ;done I am handsome boy..
Shell进程的特殊状态变量说明
位置变量 | 做用说明 |
---|---|
$? | 获取执行上一个指令的执行状态返回值(0为成功,非零为失败),这个变量最经常使用 |
$$ | 获取当前执行的Shell脚本的进程号(PID),这个变量不经常使用,了解便可 |
$! | 获取上一个在后台工做的进程的进程号(PID),这个变量不经常使用,了解便可 |
$_ | 获取在此以前执行的命令或脚本的最后一个参数,这个变量不经常使用,了解便可 |
进程参数实践
[root@mico scripts]# echo $? 0 [root@mico scripts]# echo $$ 1368 [root@mico scripts]# echo $! [root@mico scripts]# echo $_ Echo
Bash Shell常见的内部命令:echo
、eval
、exec
、export
、read
、shift
参数 | 参数说明 |
---|---|
-n | 不要追加换行 |
-e | 启用下列反斜杠转义的解释 |
-E | 显式地抑制对于反斜杠转义的解释 |
`echo' 对下列反斜杠字符进行转义:
\n
:换行\r
:回车\t
:横向制表符\b
:退格\v
:纵向制表符\c
:抑制更多的输出在命令行中使用
[root@mico scripts]# read 132 [root@mico scripts]# echo $REPLY 132 [root@mico scripts]# read mico 456 [root@mico scripts]# echo $mico 456 [root@mico scripts]# echo $REPLY 132
在脚本中使用
[root@mico scripts]# vim mico_test.sh #!/bin/bash read -p '请输入:' mico echo $mico 执行结果 [root@mico scripts]# sh mico_test.sh 请输入:mico_znix mico_znix
[root@mico scripts]# read --help -bash: read: --: 无效选项 read: 用法:read [-ers] [-a 数组] [-d 分隔符] [-i 缓冲区文字] [-n 读取字符数] [-N 读取字符数] [-p 提示符] [-t 超时] [-u 文件描述符] [-s不显示终端的任何输入] [名称 ...]
直接赋值方法
[root@mico ~]# cat parameter.sh #!/bin/bash ############################################################## # File Name: parameter.sh # Version: V1.0 # Author: mico # Created Time : 2019-07-18 17:50:45 # Description: ############################################################## name=MICO age=18 sex=girl hobby=`ls` ethFile=/etc/sysconfig/network-scripts/ifcfg-eth0 echo $hobby ls $ethFile [root@mico ~]# sh parameter.sh default.pass Django-Blog Django-Blog.tar parameter.sh practices scripts server test.sh variable.sh /etc/sysconfig/network-scripts/ifcfg-eth0
交互式设置变量 read
[root@mico ~]# vim keyword.sh #!/bin/bash ############################################################## # File Name: keyword.sh # Version: V1.0 # Author: mico # Created Time : 2019-07-18 18:42:31 # Description: ############################################################## read -p "请输入您的学号:" number read -s -p "请输入姓名:" name echo echo "您的学号:"$number echo "您的姓名:"$name [root@mico ~]# sh keyword.sh 请输入您的学号:20190729 请输入姓名: 您的学号:20190729 您的姓名:youka
脚本内容↓
[root@mico ~]# cat keyword.sh #!/bin/bash ############################################################## # File Name: keyword.sh # Version: V1.0 # Author: mico # Created Time : 2019-07-18 18:42:31 # Description: ############################################################## read -p "请输入您的学号:" number read -s -p "请输入姓名:" name echo echo "您的学号:"$number echo "您的姓名:"$name [root@mico ~]# vim host_start.sh [root@mico ~]# sh host_start.sh 请输入主机名:mico 请输入IP地址的主机位:180 是否重启服务器:{yes/no}no 请稍后手动重启系统!
表达式 | 说明 |
---|---|
${parameter} | 返回变量$parameter的内容 |
${#parameter} | 返回变内容的长度(按字符),也适用于特殊变量 |
${parameter:offset} | 在变量${parameter}中,从位置offset以后开始提取子串到结尾 |
${parameter:offset:length} | 在变量${parameter}中,从位置offset以后开始提取长度为length的子串 |
${parameter#word} | 从变量${parameter}开头开始删除最短匹配的word子串 |
${parameter##word} | 从变量${parameter}开头开始删除最长匹配的word子串 |
${parameter%word} | 从变量${parameter}结尾开始删除最短匹配的word子串 |
${parameter%%word} | 从变量${parameter}结尾开始删除最长匹配的word子串 |
${parameter/pattem/string} | 使用string代替第一个匹配的pattern |
${parameter//pattem/string} | 使用string代替全部匹配的pattern |
[root@mico ~]# export TEMP="Here is Linux" [root@mico ~]# echo ${#TEMP} 13 [root@mico ~]# echo $TEMP|wc -L 13 [root@mico ~]# expr length "$TEMP" 13 [root@mico ~]# echo "$TEMP" Here is Linux [root@mico ~]# echo "$TEMP"|awk '{print length($0)}' 13 [root@mico ~]# time echo ${#TEMP} 13 real 0m0.000s user 0m0.000s sys 0m0.000s [root@mico ~]# time echo $TEMP|wc -L 13 real 0m0.002s user 0m0.000s sys 0m0.002s [root@mico ~]#
[root@mico scripts]# mico=abcABC123ABCabc [root@mico scripts]# echo ${mico#abc} ABC123ABCabc [root@mico scripts]# echo ${mico##abc} ABC123ABCabc [root@mico scripts]# echo ${mico%abc} abcABC123ABC [root@mico scripts]# echo ${mico%%abc} abcABC123ABC [root@mico scripts]# echo ${mico#a*c} ABC123ABCabc [root@mico scripts]# echo ${mico##a*c} [root@mico scripts]# echo ${mico%a*c} abcABC123ABC [root@mico scripts]# echo ${mico%%a*c} [root@mico scripts]# echo ${mico#a*C} 123ABCabc [root@mico scripts]# echo ${mico#a*C} 123ABCabc [root@mico scripts]# echo ${mico##a*C} abc [root@mico scripts]# echo ${mico%a*c} abcABC123ABC [root@mico scripts]# echo ${mico%A*c} abcABC123 [root@mico scripts]# echo ${mico%%A*c} abc
[root@mico scripts]# echo $mico abcABC123ABCabc [root@mico scripts]# echo ${mico/abc/mico} micoABC123ABCabc [root@mico scripts]# echo ${mico//abc/mico} micoABC123ABCmico
echo $(#parameter)
处理最快的缘由是通常状况下调用外部命令来处理的方式与使用内置操做的速度相差较大。在Shell编程中应该尽可能使用内置命令。
+#
表示从幵头删除匹配最短。
##
表示从开头删除匹配最长。%
表示从结尾删除匹配最短。%%
表示从结尾删除匹配最长。a*c
表示匹配的突符串,*
表示匹配全部,a*c
匹配开头为 a、中间为任意多个字符、结尾为c的字符串。a*C
表示匹配的字符串,*
表示匹配全部,a*C
匹配开头为 a、中间为任意多个字符、结尾为C的字符串。表达式 | 说明 |
---|---|
${parameter:-word} | 若是parameter的变量值为空或未赋值,则会返回word字符串并替代变量的值用途.若是变量未定义,则返回备用的值,防止变量为空值或因未定义而致使异常 |
${parameter:=word} | 若是parameter的变量值为空或未赋值,则设置这个变量值为word,并返回其值。位置变量和特殊变量不适用用途:基本同上一个${parameter>word},但该变量又额外给parameter变量赋值了 |
${parameter:?word} | 若是parameter变量值为空或未赋值,那么word字符串将被做为标准错误输出,不然输出变量的值。用途:用于捕捉因为变量未定义而致使的错误,并退出程序 |
${parameter:+word} | 若是parameter变量值为空或未赋值,则什么都不作,不然word字符串将替代变量的值 |
运算符 | 意义 顺序 |
---|---|
++ - - | 增长及减小,可前置/可结尾 |
+ | 一元正号 |
- | 一元负号 |
! | 逻辑与 |
~ | 位的取反 |
* / % | 乘法、除法、取余数 |
+ | 加法 |
- | 减法 |
<< >> | 向左位移、向右位移 |
< <= > >= | 比较运算符 |
== != | 相等 不相等 |
& | 位的AND |
^ | 位的Exclusive OR |
| | 位的OR |
&& | 逻辑AND |
|| | 逻辑OR |
?: | 条件表达式 |
= += -= *= /= %= &= ^= | 赋值运算符 |
运算操做符与运算命令 | 意义 |
---|---|
(()) | 用于整数运算的经常使用运算符,效率高 |
let | 用于整数运算,相似于"(())" |
expr | 可用于整数运算,但还有不少其余的额外功能 |
bc | Linux下的一个计算器程序(适合整数以及小数运算) |
$[] | 用于整数的运算 |
awk | awk既能够用于整数运算,也能够用于小数运算 |
declare | 定义变量值和属性,-i参数能够用于定义整形变量,作运算 |
(())
的操做方法运算操做符与运算命令 | 意义 |
---|---|
((i=i+1)) | 此种书写方法为运算后赋值法,即将i+1的运算结构赋值给变量i。注意,不能用"echo((i=i+1))"的形式输出表达式的值,但能够用echo$((i=i+1))输出其值 |
i=$((i+1)) | 能够在"(())"前加$符,表示将表达式运算后复制给i |
((8>7&&5==5)) | 能够进行比较操做,还能够加入逻辑与和逻辑或,用于条件判断 |
echo $((2+1)) | 须要直接输出运算表达式的运算结果时,能够在"(())"前加$符 |
【提示】上面涉及的数字及变量必须为整数(整型),不能是小数(浮点数)或字符串。后面的bc
和awk
命令能够用于进行小数(浮点数)运算,但通常用到的较少。
# 形式一 [root@mico scripts]# echo $((1 + 1)) 2 [root@mico scripts]# echo $((2*7-3/6+5)) 19 # 形式二 [root@mico scripts]# ((mico=2*8)) [root@mico scripts]# echo $mico 16 # 形式三 [root@mico scripts]# znix=$((2*7-3/6+5)) [root@mico scripts]# echo $znix 19
示例:
[root@mico scripts]# i=1 [root@mico scripts]# echo $((i++)) 1 [root@mico scripts]# echo $((i++)) 2 [root@mico scripts]# echo $((i--)) 3 [root@mico scripts]# echo $((i--)) 2 [root@mico scripts]# echo $((i--)) 1 [root@mico scripts]# echo $((++i)) 1 [root@mico scripts]# echo $((++i)) 2 [root@mico scripts]# echo $((++i)) 3 [root@mico scripts]# echo $((--i)) 2 [root@mico scripts]# echo $((--i)) 1 [root@mico scripts]# echo $((--i)) 0
记忆方法:++,--
变量a在前,表达式的值为a,而后a自增或自减,变量a在符号后,表达式值自增或自减,而后a值自增或自减。
[root@mico scripts]# i=1 [root@mico scripts]# i=i+1 [root@mico scripts]# echo $i i+1 [root@mico scripts]# i=1 [root@mico scripts]# let i=i+1 [root@mico scripts]# echo $i 2
[root@mico scripts]# expr 1+1 1+1 [root@mico scripts]# expr 1 + 1 2 [root@mico scripts]# expr 1 * 1 expr: 语法错误 [root@mico scripts]# expr 1 \* 1 1
[root@mico scripts]# expr 1 + 1 2 [root@mico scripts]# echo $? 0 [root@mico scripts]# expr -1 + 1 0 [root@mico scripts]# echo $? 1 [root@mico scripts]# expr a + 1 expr: 非整数参数 [root@mico scripts]# echo $? 2 $[]运算符 [root@mico scripts]# echo $[1+2] 3 [root@mico scripts]# echo $[1-2] -1 [root@mico scripts]# echo $[1*2] 2 [root@mico scripts]# echo $[1/2] 0
[root@mico scripts]# typeset -i A=2017 B=2018 [root@mico scripts]# A=A+B [root@mico scripts]# echo $A 4035
# 安装 bc 依赖于base源 [root@mico scripts]# yum -y install bc 交互模式测试bc命令 [root@mico scripts]# bc bc 1.06.95 Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006 Free Software Foundation, Inc. 1+1 2 [root@mico scripts]# echo 1+1.1|bc 2.1
[root@mico scripts]# echo 'scale=6;1/3'|bc .333333 python 命令 [root@mico scripts]# file `which yum ` /usr/bin/yum: Python script, ASCII text executable [root@mico scripts]# python >>> import os >>> os.system('df -h') >>> 1+1.1 2.1 >>>exit()
[root@mico ~]# echo "7.7 3.8"|awk '{print ($1-$2)}' 3.9 [root@mico ~]# echo "358 113"|awk '{print ($1-3)/$2}' 3.14159 [root@mico ~]# echo "3 9"|awk '{print ($1+3)*$2}' 54 [root@backup scripts]# awk BEGIN'{print 1.2+3.3}' 4.5
实现脚本:
[root@mico scripts]# cat calculator.sh #!/bin/bash read -p "请输入第一个整数:" a read -p "请输入第二个整数:" b echo $a + $b =$(($a+$b)) echo $a - $b =$(($a-$b)) echo $a \* $b =$(($a*$b)) echo $a / $b =$(($a/$b)) 脚本执行过程: [root@mico scripts]# sh calculator.sh 请输入第一个整数:12 请输入第二个整数:12 12 + 12 =24 12 - 12 =0 12 * 12 =144 12 / 12 =1
[root@mico scripts]# vim calculator2.sh #!/bin/bash echo $(($1)) 脚本执行过程: [root@mico scripts]# sh calculator2.sh 1+1 2 [root@mico scripts]# sh calculator.sh 1*9 9
脚本内容
[root@mico scripts]# vim count.sh #!/bin/bash Num=`seq -s + 1 10` echo $Num=$(($Num))
脚本执行结果
[root@mico scripts]# sh count.sh 1+2+3+4+5+6+7+8+9+10=55
shell脚本中批量注释的方法
<<'EOF'
文件内容
EOF
或使用 exit
能够注释其以后的全部内容(相似注释,实质为不执行后面的内容)