有了第一篇的铺垫,现在可以来写一些比较有趣的东西了
第一篇链接:https://blog.youkuaiyun.com/aoxixi/article/details/89843929
1、对谈式脚本:变量内容由用户决定
有时候我们需要用户输入一些内容,好让程序可以顺利运行 ,用 read指令,写一个script:
比如下面的脚本的作用:用户输入他的姓和名,输出全名
[root@www scripts]# vi sh02.sh
#!/bin/bash
# Program:
# User inputs his first name and last name. Program shows his full
name.
# History:
# 2005/08/23 VBird First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
read -p "Please input your first name: " firstname # 提示使用者输入 ,注意这里的空格使用,变量前面加空格
read -p "Please input your last name: " lastname # 提示使用者输入
echo -e "\nYour full name is: $firstname $lastname" # 结果由屏幕输出
结果:
注意:1.这里的空格使用,firstname 变量前面加空格
2.变量在下面引用 $加变量名 ( 比如 $lastname)
I、 补充的小知识
执行脚本时 source sh02.sh 和./sh02.sh区别
已知在sh02.sh 的脚本中,我们定义了两个变量,所以用来查看一下变量还在不在
- 上面两张图可以看出,source 执行的,变量还在,但是./sh02.sh执行的,变量就不在了
- 这是因为二者执行的时候,source 是直接在本bash 执行的 ,而后者是新开一个bash,执行完之后,之后销毁新开的bash,并返回结果,所以在查询变量的时候,查不到变量
- 这也是为啥你不注销系统而要让某些写入 ~/.bashrc 的设定生效时,需要使用『 source ~/.bashrc 』而不能使用『 bash ~/.bashrc 』是一样 的啊!
2、随日期变化的文件名:利用date进行档案的建档
下面的脚本的作用:输入用户名,脚本根据时间来建立三个文件
#!/bin/bash
# Program:
# Program creates three files, which named by user's input
# and date command.
# History:
# 2005/08/23 VBird First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
#1、让使用者输入文件名,并取得fileuser这个文件名
echo -e "I will use 'touch' command to create 3 file"
read -p "Please input your filename:" fileuser #提示使用者输入用户名
#2、为了避免使用者随意按Enter,利用变量功分析文档名是否有设定?
filename=${fileuser:-"filename"} #开始判断是否配置有文件名,注意空格 filename后面一定不要加空格
#3、利用date指令来取得所需要的文档名
date1=$(date --date='2 days ago' +%Y%m%d) #前两天的日期,加号前面要加空格
date2=$(date --date='1 days ago' +%Y%m%d) #前一天的日期
date3=$(date +%Y%m%d) #今天的日期
file1=${filename}${date1} #配置文件名 这里一定是${}而不是$()
file2=${filename}${date2}
file3=${filename}${date3}
#4、建立文件
touch "$file1"
touch "$file2"
touch "$file3"
输出结果:看到建立了三个用时间和用户名 命名的文件了
注意: $()和 ${}的区别 还有 $(())
$( ) 与 ` ` (反引号)
在 bash shell 中,$( ) 与 ` ` (反引号) 都是用来做命令替换用(command substitution)的。都是用来重组命令行:完成引号里的命令行,然后将其结果替换出来,再重组命令行。
比如要实现两个时间的相减可以用:
echo $((`date --date="20190506" +%s`-`date +%s`))
echo $(($(date --date="20190506" +%s)-$(date +%s)))
而$(())在运算的时候,比如加减乘除的时候,就要用 $(()) 括起来
数值的运算,简单的加减乘数: 我们可以使用 declare 来定义变量的类型吧? 当变量定义成为整数后才能够进 行加减运算啊 也可以利用 $((计算式)) 来进行数值运算
${} 用来做变量的替换:
一般情况下,$var 与 ${var} 并没有啥不一样。
但是用 ${ } 会比较精确的界定变量名称的范围,比方说:
A=B
echo $AB
原本是打算先将 $A 的结果替换出来,然后再补一个 B 字母于其后,
但在命令行上,真正的结果却是只会提换变量名称为 AB 的值出来…
若使用 ${ } 就没问题了:
echo ${A}B
详细请看博客:https://www.cnblogs.com/xunbu7/p/6187017.html
3、shell脚本后面带参数($0,$1…)
既然我们可以通过read 的方式来让用户输入参数来讲进行交互,那么可不可以用默认的方式来传递参数呢? 请看下面示例:
再次之前,我们来了解一下 文件名和参数关系
/ath/to/scritname ot1 ot2 ot3 ot4
$0 $1 $2 $3 $4
脚本的文件名就是 $0 第一个参数就是 $1 以此类推
还有一些特殊的变量可以在script 内使用来呼叫参数
$# :代表后接的参数『个数』,以上表为例这里显示为『 4 』;
$@ :代表『 "$1" "$2" "$3" "$4"』之意,每个发量是独立的(用双引号括起来);
$* :代表『 "$1c$2c$3c$4" 』,其中 c 为分隔字符,默认为空键, 所以本例中代表『 "$1 $2 $3 $4" 』之意。
#!/bin/bash
# Program:
# program shows the script name,parameters..
#History
#2019/05/04 zyr
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
echo "the script name is ==> $0" #输出第0个参数 也就是文件名
echo "total parameters number is ==> $#" #所有参数的个数
[ "$#" -lt 2 ] && echo "the number of parameter is less than 2. stop here" \
&& exit 0 #如果参数个数小于2的话,就提示用户,并退出
echo "your whole parameter is ==>'$@'" #输出所有参数
echo "the lst parameter ==> '$1'" #第一个参数 参数1
echo "the 2nd parameter ==> '$2'" #输出第二个参数
也就是说之后做操作的时候,就可以直接用 $1 $2 $3 $# $@等等来直接获取参数了
参数的偏移shift
就是在前面拿掉几个参数的意思,而且后面可以接参数,代表拿掉最前面的几个参数的意思 :shift 3 // 就是去掉前面三个参数 不带参数就默认为1
#!/bin/bash
# Program:
# program shows the script name,parameters..
#History
#2019/05/04 zyr
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
echo "the script name is ==> $0"
echo "total parameters number is ==> $#"
[ "$#" -lt 2 ] && echo "the number of parameter is less than 2. stop here" \
&& exit 0
echo "your whole parameter is ==>'$@'"
echo "the lst parameter ==> '$1'"
echo "the 2nd parameter ==> '$2'"
shift 2
echo "total parameters number is ==> $#"
echo "total parameters is ==> $@"
4、shell中的判断
a.test指令的test功能
比如测试一个文件是否存在:
test -e /sh06 && echo "exit"||echo "no" //返回值 存在输出前者 不存在输出后者
更多参数:
文件类型判断
-e 该『档名』是否存在?(常用)
-f 该『档名』是否存在且为档案(file)?(常用)
-d 该『文件名』是否存在且为目录(directory)?(常用)
-b 该『档名』是否存在且为一个 block device 装置?
-c 该『档名』是否存在且为一个 character device 装置?
-S 该『档名』是否存在且为一个 Socket 档案
-p 该『档名』是否存在且为一个 FIFO (pipe) 档案?
-L 该『档名』是否存在且为一个连结档?
关于文档权限的测试
-r 侦测该档名是否存在且具有『可读』的权限?
-w 侦测该档名是否存在且具有『可写』的权限?
-x 侦测该档名是否存在且具有『可执行』的权限?
-u 侦测该文件名是否存在且具有『SUID』的属性?
-g 侦测该文件名是否存在且具有『SGID』的属性?
-k 侦测该文件名是否存在且具有『Sticky bit』的属性?
-s 侦测该档名是否存在且为『非空白档案』?
两个档案之间的比较 例如: test n1 -eq n2
-nt (newer than)判断 file1 是否比 file2 新
-ot (older than)判断 file1 是否比 file2 旧
-ef 判断 file1 不 file2 是否为同一档案,可用在刞断 hard link 的刞定上。 主要意义在判定,两个档案是否均指向同一个 inode 里!
关于两个整数之间的判定,例如 test n1 -eq n2
-eq 两数值相等 (equal)
-ne 两数值于等 (not equal)
-gt n1 大于 n2 (greater than)
-lt n1 小于 n2 (less than)
-ge n1 大于等于 n2 (greater than or equal)
-le n1 小于等于 n2 (less than or equal)
判定字符串的数据
test -z string 判定字符串是否为 0 ?若 string 为空字符串,则为 true
test -n string刞定字符串是否非为 0 ?若 string 为空字符串,则为 false。注: -n 亦可省略
test str1 = str2 判定 str1 是否等于 str2 ,若相等,则回传 true
test str1 != str2 判定 str1 是否则等于 str2 ,若相等,则回传 false
多重条件判定,例如: test -r filename -a -x filename
-a(and)两状况同时成立!例如 test -r file -a -x file,则 file 同时具r 不 x 权限时,才回传 true。
-o(or)两状况任何一个成立!例如 test -r file -o -x file,则 file 同时具有r或 x 权限时,就可回传 true。
! 反相状态,如 test ! -x file ,当 file 并具有 x 时,回传 true
除了test 之外,还可以利用判断符号 [] 中括号来进行数据判断!
比如 如果要知道$HOME这个变量是否为空 可以这样做:
[ -z "$HOME" ];echo $?
[ 1 -eq 2 ];echo $? //注意这里中括号两边都要打空格 就是if 判断的时候的那个'[]'
注意:在使用中括号的时候,每一个组件都需要空格键来分割。在中括号内的变数,最好都以双引号括号起来; 在中括号内的常数,最好都以单或双引号括号起来
案例:
#!/bin/bash
# Program:
# This program shows the user's choice
# History:
# 2019/05/04 zyr First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
read -p "Please input(Y/N):" yn
[ "$yn" == "Y" -o "$yn" == "y" ] && echo "OK ,continue" && exit 0
[ "$yn" == "N" -o "$yn" == "n" ] && echo "oh ,interrupt" && exit 0
echo "I dont konw what is your chioce" && exit 0
结果:
了解了如何用参数来进行判断比较,下面我们要来真正的条件判断啦!
后续内容在:一起来写Shell Script 03 https://mp.youkuaiyun.com/mdeditor/89857512