参考:

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: ”的内容:
[dmtsai@study 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 ,该如何是好?
[dmtsai@study 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!那我们来玩玩看,如果我们要
使用者输入两个变量, 然后将两个变量的内容相乘,最后输出相乘的结果,那可以怎么做?
[dmtsai@study 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 啊!就是:
[dmtsai@study bin]$ echo $(( 13 % 3 ))
1
这样了解了吧?另外,如果你想要计算含有小数点的数据时,其实可以通过 bc 这个指令的协
助喔! 例如可以这样做:
[dmtsai@study bin]$ echo "123.123*55.9" |  bc
6882.575
了解了 bc 的妙用之后,来让我们测试一下如何计算 pi 这个东西呢?
数值运算:通过 bc 计算 pi
其实计算 pi 时,小数点以下位数可以无限制的延伸下去!而 bc 有提供一个运算 pi 的函数,
只是想要使用该函数必须要使用 bc -l 来调用才行。 也因为这个小数点以下位数可以无线延伸
运算的特性存在,所以我们可以通过下面这只小脚本来让使用者输入一个“小数点为数值”,
以让 pi 能够更准确!
[dmtsai@study 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 會不會生效?看一下底下的執行結果:

[dmtsai@study bin]$ echo ${firstname} ${lastname}
<==確認了,這兩個變數並不存在喔!
[dmtsai@study bin]$ sh showname.sh
Please input your first name: VBird <==這個名字是鳥哥自己輸入的
Please input your last name: Tsai Your full name is: VBird Tsai <==看吧!在 script 運作中,這兩個變數有生效
[dmtsai@study 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 來執行指令那就不一樣了!同樣的腳本我們來執行看看:

[dmtsai@study bin]$ source showname.sh
Please input your first name: VBird
Please input your last name: Tsai Your full name is: VBird Tsai
[dmtsai@study bin]$ echo ${firstname} ${lastname}
VBird Tsai <==嘿嘿!有資料產生喔!

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

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

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

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

    参考: http://linux.vbird.org/linux_basic/0340bashshell-scripts.php#script_be http://www.runoob.com/lin ...

  2. 鸟哥的 Linux 私房菜Shell Scripts篇(四)

    12.4 条件判断式 只要讲到『程式』的话,那么条件判断式,亦即是『 if then 』这种判别式肯定一定要学习的!因为很多时候,我们都必须要依据某些资料来判断程式该如何进行.举例来说,我们在上头的a ...

  3. 鸟哥的 Linux 私房菜Shell Scripts篇(三)

    参考: http://linux.vbird.org/linux_basic/0340bashshell-scripts.php#script_be http://www.runoob.com/lin ...

  4. 拒绝从入门到放弃_《鸟哥的 Linux 私房菜 — 基础学习篇(第三版)》必读目录

    目录 目录 前言 关于这本书 必看知识点 最后 前言 相信部分刚进入这个行业的新同学会对一个问题感到疑惑,为什么从培训学校出来的学员不被欢迎? 这里记录下一些我个人的看法(博主也曾有面试新员工的经历) ...

  5. 每周一书-《鸟哥的Linux私房菜基础学习篇(第四版)》台湾原版,你想要吗?

     首先说明,本周活动有效时间为2016年10月19日到2016年10月31日.   目在介绍这本书之前,首先要感谢QQ号为:1084830483(路在远方),来自哈尔滨工程大学的同学赠送给玄魂工作室的 ...

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

    最近,一直在写PPC的模拟器和汇编器,也在做设计.所以重新看了看<鸟哥的Linux私房菜>,还是有好多命令不太熟悉.就打算写几篇blog记下来. 1. nl [-bnw] filename ...

  7. 《鸟哥的Linux私房菜-基础学习篇(第三版)》(三)

    第2章 Linxu怎样学习         1. Linux当前的应用角色 当前的Linux常见的应用可略分为企业应用和个人应用双方面. 首先谈了企业环境的利用. 1)网络server. 2)关键任务 ...

  8. 鸟哥的Linux私房菜 基础学习篇读书笔记(9):Linux磁盘与文件系统管理(2)

    上一篇文章主要从理论上分析了Linux的Ext2文件系统.这一篇主要解说怎样查看Linux的文件系统的容量以及解说Linux文件系统中的连接文件. 能够通过df和du命令来查看磁盘与文件夹的容量.df ...

  9. 《鸟哥的Linux私房菜-基础学习篇(第三版)》(四)

    第3章 主机规划与磁盘分区        1. Linux与硬件的搭配        首先谈了认识计算机的硬件配置. 然后谈了选择与Linux搭配的主机配置. 在Linuxserver中,内存的重要性 ...

随机推荐

  1. Docker: connection reset by peer

    想来,对docker的学习和实践,已经一年有余了,而我关于这样的文章,只有为数不多的几篇.今天借使用docker中发生的一种异常情况为例,写此篇幅. 这个是在centos7.0 ..netcore2. ...

  2. 理解Array.prototype.fill和Array.from

    之所以将这两个方法放在一起说,是因为经常写这样的代码: Array.from({length: 5}).fill(0),看起来很简洁,但是踩到坑之后才发现自己对这两个方法实在是不求甚解. Array. ...

  3. java对文件的检索

    先说下思路吧. 1.先把xls等文件转换为静态html文件:可以用很多插件,类似我的博客地址: http://www.cnblogs.com/Alandre/p/3221006.html 2.再对转的 ...

  4. C#效率优化(2)-- 方法内联

    一.JIT编译器可以通过将方法内联展开(Method Inline Expansion)来提升效率,类似C++中的内联函数(Inline Function),与C++的内联函数不同的是,C#并不支持内 ...

  5. 开源网站流量统计系统Piwik源码分析——参数统计(一)

    Piwik现已改名为Matomo,这是一套国外著名的开源网站统计系统,类似于百度统计.Google Analytics等系统.最大的区别就是可以看到其中的源码,这正合我意.因为我一直对统计的系统很好奇 ...

  6. 看懂「www.google.com」背后的逻辑

    在前两篇文章中,我们完整的描述了计算机网络 OSI 五层模型的相关内容.那么,本篇将会从一个实践案例开始,带你从整体上重新认识我们的计算机网络. 我们以访问 Google 为例,当我们在浏览器地址栏中 ...

  7. 深入理解JavaScript的事件循环(Event Loop)

    一.什么是事件循环 JS的代码执行是基于一种事件循环的机制,之所以称作事件循环,MDN给出的解释为 因为它经常被用于类似如下的方式来实现 while (queue.waitForMessage()) ...

  8. python的Web框架,会话保持及Form表单

    会话 从打开浏览器访问到关闭浏览器,这就是一次会话. cookie 技术 cookie是保存在浏览器的,安全度比较低. # 设置cookie范式,在view中设置 def index(request) ...

  9. kubernetes系列(一)安装和配置

    谈到kubernetes(或者说k8s)不得不提到云计算.虚拟化以及容器技术,相关介绍网上一大堆,不再赘述.而kubernetes的出现就是为了高效的管理云端运行的docker容器. 环境 docke ...

  10. [转]Node.js tutorial in Visual Studio Code

    本文转自:https://code.visualstudio.com/docs/nodejs/nodejs-tutorial Node.js tutorial in Visual Studio Cod ...