鸟哥的 Linux 私房菜Shell Scripts篇(二)

参考:

http://linux.vbird.org/linux_basic/0340bashshell-scripts.php#script_be

http://www.runoob.com/linux/linux-tutorial.html

12.2 简单的 shell script 练习

在第一支 shell script 撰写完毕之后,相信你应该具有基本的撰写功力了。接下来,在开始更
深入的程序概念之前,我们先来玩一些简单的小范例好了。 下面的范例中,达成结果的方式
相当的多,建议你先自行撰写看看,写完之后再与鸟哥写的内容比对, 这样才能更加深概念
喔!好!不?唆,我们就一个一个来玩吧!

12.2.1 简单范例

下面的范例在很多的脚本程序中都会用到,而下面的范例又都很简单!值得参考看看喔!
对谈式脚本:变量内容由使用者决定
很多时候我们需要使用者输入一些内容,好让程序可以顺利运行。 简单的来说,大家应该都
有安装过软件的经验,安装的时候,他不是会问你“要安装到那个目录去”吗? 那个让使用者
输入数据的动作,就是让使用者输入变量内容啦。
你应该还记得在十章 bash 的时候,我们有学到一个 read 指令吧?现在,请你以 read 指令的
用途,撰写一个 script ,他可以让使用者输入:1. first name 与 2. last name, 最后并且在屏
幕上显示:“Your full name is: ”的内容:
[[email protected] bin]$ vim showname.sh
#!/bin/bash
# Program:
# User inputs his first name and last name. Program shows his full name.
# History:
# 2015/07/16 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}" # 结果由屏幕输出

将上面这个 showname.sh 执行一下,你就能够发现使用者自己输入的变量可以让程序所取
用,并且将他显示到屏幕上! 接下来,如果想要制作一个每次执行都会依据不同的日期而变
化结果的脚本呢?

随日期变化:

利用 date 进行文件的创建想像一个状况,假设我的服务器内有数据库,数据库每天的数据都不太一样,因此当我备份
时,希望将每天的数据都备份成不同的文件名, 这样才能够让旧的数据也能够保存下来不被
覆盖。哇!不同文件名呢!这真困扰啊?难道要我每天去修改 script ?
不需要啊!考虑每天的“日期”并不相同,所以我可以将文件名取成类似: backup.2015-07-
16.data , 不就可以每天一个不同文件名了吗?呵呵!确实如此。那个 2015-07-16 怎么来
的?那就是重点啦!接下来出个相关的例子: 假设我想要创建三个空的文件 (通过 touch)
文件名最开头由使用者输入决定,假设使用者输入 filename 好了,那今天的日期是
2015/07/16 , 我想要以前天、昨天、今天的日期来创建这些文件,亦即 filename_20150714,
filename_20150715, filename_20150716 ,该如何是好?
[[email protected] bin]$ vim create_3_filename.sh
#!/bin/bash
# Program:
# Program creates three files, which named by user‘s input and date command.
# History:
# 2015/07/16 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 files." # 纯粹显示信息
read -p "Please input your filename: " fileuser # 提示使用者输入
# 2\. 为了避免使用者随意按 Enter ,利用[变量功能](../Text/index.html#variable_other_re)分析文件名是否有设置?
filename=${fileuser:-"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}"

上面的范例鸟哥使用了很多在第十章介绍过的概念: 包括小指令“ $(command) ”的取得讯
息、变量的设置功能、变量的累加以及利用 touch 指令辅助! 如果你开始执行这个
create_3_filename.sh 之后,你可以进行两次执行:一次直接按 [Enter] 来查阅文件名是啥?
一次可以输入一些字符,

数值运算:简单的加减乘除

各位看官应该还记得,我们可以使用 declare 来定义变量的类型吧? 当变量定义成为整数后
才能够进行加减运算啊!此外,我们也可以利用“ $((计算式)) ”来进行数值运算的。 可
惜的是, bash shell 里头默认仅支持到整数的数据而已。OK!那我们来玩玩看,如果我们要
使用者输入两个变量, 然后将两个变量的内容相乘,最后输出相乘的结果,那可以怎么做?
[[email protected] bin]$ vim multiplying.sh
#!/bin/bash
# Program:
# User inputs 2 integer numbers; program will cross these two numbers.
# History:
# 2015/07/16 VBird First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
echo -e "You SHOULD input 2 numbers, I will multiplying them! \n"
read -p "first number: " firstnu
read -p "second number: " secnu
total=$((${firstnu}*${secnu}))
echo -e "\nThe result of ${firstnu} x ${secnu} is ==> ${total}"

在数值的运算上,我们可以使用“ declare -i total=${firstnu}*${secnu} ” 也可以使用上面的方式
来进行!基本上,鸟哥比较建议使用这样的方式来进行运算:
var=$((运算内容))
不但容易记忆,而且也比较方便的多,因为两个小括号内可以加上空白字符喔! 未来你可以
使用这种方式来计算的呀!至于数值运算上的处理,则有:“ +, -, , /, % ”等等。 那个 % 是取
余数啦~举例来说, 13 对 3 取余数,结果是 13=43+1,所以余数是 1 啊!就是:
[[email protected] bin]$ echo $(( 13 % 3 ))
1
这样了解了吧?另外,如果你想要计算含有小数点的数据时,其实可以通过 bc 这个指令的协
助喔! 例如可以这样做:
[[email protected] bin]$ echo "123.123*55.9" |  bc
6882.575
了解了 bc 的妙用之后,来让我们测试一下如何计算 pi 这个东西呢?
数值运算:通过 bc 计算 pi
其实计算 pi 时,小数点以下位数可以无限制的延伸下去!而 bc 有提供一个运算 pi 的函数,
只是想要使用该函数必须要使用 bc -l 来调用才行。 也因为这个小数点以下位数可以无线延伸
运算的特性存在,所以我们可以通过下面这只小脚本来让使用者输入一个“小数点为数值”,
以让 pi 能够更准确!
[[email protected] bin]$ vim cal_pi.sh
#!/bin/bash
# Program:
# User input a scale number to calculate pi number.
# History:
# 2015/07/16 VBird First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
echo -e "This program will calculate pi value. \n"
echo -e "You should input a float number to calculate pi value.\n"
read -p "The scale number (10~10000) ? " checking
num=${checking:-"10"} # 开始判断有否有输入数值
echo -e "Starting calcuate pi value. Be patient."
time echo "scale=${num}; 4*a(1)" | bc -lq

上述数据中,那个 4*a(1) 是 bc 主动提供的一个计算 pi 的函数,至于 scale 就是要 bc 计
算几个小数点下位数的意思。当 scale 的数值越大, 代表 pi 要被计算的越精确,当然用掉的
时间就会越多!因此,你可以尝试输入不同的数值看看!不过,最好是不要超过 5000 啦!因
为会算很久! 如果你要让你的 CPU 随时保持在高负载,这个程序算下去你就会知道有多操
CPU ?! ^_^
Tips 鸟哥的实验室中,为了要确认虚拟机的效率问题,所以很多时候需要保持虚拟机在忙碌
的状态~鸟哥的学生就是丢这只程序进去系统跑! 但是将 scale 调高一些,那计算就得要花
比较多时间~用以达到我们需要 CPU 忙碌的状态喔!

这样可以判断你的脚本是否设计正确喔!

12.2.2 script 的執行方式差異 (source, sh script, ./script)

不同的 script 執行方式會造成不一樣的結果喔!尤其影響 bash 的環境很大呢!腳本的執行方式除了前面小節談到的方式之外,還可以利用 source 或小數點 (.) 來執行喔!那麼這種執行方式有何不同呢?當然是不同的啦!讓我們來說說!

  • 利用直接執行的方式來執行 script

當使用前一小節提到的直接指令下達 (不論是絕對路徑/相對路徑還是 ${PATH} 內),或者是利用 bash (或 sh) 來下達腳本時, 該 script 都會使用一個新的 bash 環境來執行腳本內的指令!也就是說,使用這種執行方式時, 其實 script 是在子程序的 bash 內執行的!我們在第十章 BASH 內談到 export 的功能時,曾經就父程序/子程序談過一些概念性的問題, 重點在於:『當子程序完成後,在子程序內的各項變數或動作將會結束而不會傳回到父程序中』! 這是什麼意思呢?

我們舉剛剛提到過的 showname.sh 這個腳本來說明好了,這個腳本可以讓使用者自行設定兩個變數,分別是 firstname 與 lastname,想一想,如果你直接執行該指令時,該指令幫你設定的 firstname 會不會生效?看一下底下的執行結果:

[[email protected] bin]$ echo ${firstname} ${lastname}
    <==確認了,這兩個變數並不存在喔!
[[email protected] bin]$ sh showname.sh
Please input your first name: VBird <==這個名字是鳥哥自己輸入的
Please input your last name:  Tsai 

Your full name is: VBird Tsai      <==看吧!在 script 運作中,這兩個變數有生效
[[email protected] bin]$ echo ${firstname} ${lastname}
    <==事實上,這兩個變數在父程序的 bash 中還是不存在的!

上面的結果你應該會覺得很奇怪,怎麼我已經利用 showname.sh 設定好的變數竟然在 bash 環境底下無效!怎麼回事呢? 如果將程序相關性繪製成圖的話,我們以下圖來說明。當你使用直接執行的方法來處理時,系統會給予一支新的 bash 讓我們來執行 showname.sh 裡面的指令,因此你的 firstname, lastname 等變數其實是在下圖中的子程序 bash 內執行的。 當 showname.sh 執行完畢後,子程序 bash 內的所有資料便被移除,因此上表的練習中,在父程序底下 echo ${firstname} 時, 就看不到任何東西了!這樣可以理解嗎?

圖12.2.1、showname.sh 在子程序當中運作的示意圖

  • 利用 source 來執行腳本:在父程序中執行

如果你使用 source 來執行指令那就不一樣了!同樣的腳本我們來執行看看:

[[email protected] bin]$ source showname.sh
Please input your first name: VBird
Please input your last name:  Tsai

Your full name is: VBird Tsai
[[email protected] bin]$ echo ${firstname} ${lastname}
VBird Tsai  <==嘿嘿!有資料產生喔!

竟然生效了!沒錯啊!因為 source 對 script 的執行方式可以使用底下的圖示來說明! showname.sh 會在父程序中執行的,因此各項動作都會在原本的 bash 內生效!這也是為啥你不登出系統而要讓某些寫入 ~/.bashrc 的設定生效時,需要使用『 source ~/.bashrc 』而不能使用『 bash ~/.bashrc 』是一樣的啊!

圖12.2.2、showname.sh 在父程序當中運作的示意圖

原文地址:https://www.cnblogs.com/-wanglei/p/10063171.html

时间: 2024-08-02 17:25:56

鸟哥的 Linux 私房菜Shell Scripts篇(二)的相关文章

鸟哥的 Linux 私房菜Shell Scripts篇(一)

12.1 什么是 Shell scripts 什么是 shell script (程序化脚本) 呢?就字面上的意义,我们将他分为两部份. 在" shell"部分,我们在 十章的 BASH 当中已经提过了,那是一个命令行下面让我们与系统沟通的一个工具接口.那么" script "是啥? 字面上的意义, script 是"脚本.剧本"的意思.整句话是说,shell script 是针对 shell 所写的"剧本!"什么东西啊?其实

鸟哥的Linux私房菜——基础学习篇 —— 笔记2

at 语法 == 注意,输入at之后便进入命令行模式 ------- 不管怎么样,只会执行一次. [test @test test]# at [-m] TIME (输入工作指令)[test @test test]# atq (查看当前工作流程)[test @test test]# atrm [jobnumber] (删除流程) -m :执行at规范的工作流程时,将屏幕输出结果mail给输入指令的用户TIME :时间格式,有如下几个: ================== 格式有多种,但没有可以间

【Linux】鸟哥的Linux私房菜基础学习篇整理(七)

1. test命令的测试功能.测试的标志:(1)关于文件类型的检测 test [-efdbcSpL] filename-e:该文件名是否存在:-f:该文件名是否为文件:-d:该文件名是否为目录:-b:该文件名是否存在且为一个block device设备:-c:该文件名是否存在且为一个character device设备:-S:该文件名是否存在且为一个Socket文件:-p:该文件名是否存在且为一个FIFO文件:-L:该文件名是否存在且为一个连接文件.(2)关于文件权限的检测 test [-r]

【Linux】鸟哥的Linux私房菜基础学习篇整理(五)

1. type [-tpa] name:查看name命令是否为bash内置命令.参数:type:不加任何参数,type会显示出那么是外部命令还是bash的内置命令:-t:当加入-t参数时,type会通过如下关键字显示其意义: file:表示为外部命令 alias:表示为命名别名 builtin:表示为bash的内置命令-p:如果后面接的name为外置命令时,才会显示完整文件名:-a:会由PATH变量定义的路径中,将含有name的命令都列出来,包含别名. 2. unset name:取消变量名na

【Linux】鸟哥的Linux私房菜基础学习篇整理(八)

1. useradd [-u UID] [-g 初始用户组] [-G 次要用户组] [-mM]\   [-c 说明栏] [-d 主文件夹绝对路径] [-r] [-s shell] 用户账号名:新增用户.参数:-u:后面接UID,是一组数字,直接指定一个特定的UID给这个账号:-g:后面接初始用户组,该用户组的GID会被放置到/etc/passwd的第四个字段:-G:后面接这个账号还可以加入的用户组:-M:强制,不创建用户主文件夹(系统账号默认值):-m:强制,创建用户主文件夹(一般账号默认值):

【Linux】鸟哥的Linux私房菜基础学习篇整理(一)

最近,一直在写PPC的模拟器和汇编器,也在做设计.所以重新看了看<鸟哥的Linux私房菜>,还是有好多命令不太熟悉.就打算写几篇blog记下来. 1. nl [-bnw] filename:添加行号打印参数:-b:指定行号指定的方式,主要有两种: -b a:表示不论是否为空行,也同样列出行号(类似cat -n): -b t:如果有空行,空的那一行不要列出行号(默认值).-n:列出行号表示的方法,主要有三种: -n ln:行号在屏幕的最左方显示: -n rn:行号在自己字段的最右方显示,且不加0

【Linux】鸟哥的Linux私房菜基础学习篇整理(二)

1. dumpe2fs [-bh] devicename:查询superblock信息.参数:-b:列出保留为坏道的部分:-h:列出superblock的数据,不会列出其他的区段内容. 2. df [-ahikHTm] 目录或文件名:列出文件系统的整理磁盘使用量.参数:-a:列出所有的文件系统,包括系统特有的/proc等文件系统:-k:以KB的容量显示各文件系统:-m:以MB的容量显示各文件系统:-h:以人们易阅读的GB.MB.KB等格式自行显示:-H:以M=1000K替代M=1024K的进位方

【Linux】鸟哥的Linux私房菜基础学习篇整理(九)

1. quotacheck [-avugfM] [/mount_point]:扫描文件系统并创建Quota配置文件.参数:-a:扫描所有在/etc/mtab内,含有quota支持的文件系统,加上此参数后,不必写/mount_point:-u:针对用户扫描文件与目录的使用情况,会新建aquota.user:-g:针对用户组扫描文件与目录的使用情况,会新建aquota.group:-v:显示扫描过程的信息:-f:强制扫描文件系统,并写入新的quota配置文件(危险):-M:强制以读写的方式扫描文件系

Bombe 【Linux】鸟哥的Linux私房菜基础学习篇整理(三)

1. gzip [-cdtv#] filename:压缩.参数:-c:将压缩的数据输出到屏幕上,可通过数据重定向进行处理:-d:解压缩的参数:-t:可以用来检验一个压缩文件的一致性,查看文件有无错误:-v:可以显示出原文件/压缩文件的压缩比等信息:-#:压缩等级,1最快(压缩比最差),9最慢(压缩比最好),默认6. 2. zcat *.gz:读取gzip压缩文件. 3. bzip2 [-cdkzv#] filename:压缩.参数:-c:将压缩过程中产生的数据输出到屏幕上:-d:解压缩的参数:-