zoukankan      html  css  js  c++  java
  • 鸟哥的 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: ”的内容:
    [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 " Your 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! "
    read -p "first number: " firstnu
    read -p "second number: " secnu
    total=$((${firstnu}*${secnu}))
    echo -e " The 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. "
    echo -e "You should input a float number to calculate pi value. "
    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} 時, 就看不到任何東西了!這樣可以理解嗎?

    showname.sh 在子程序當中運作的示意圖
    圖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 』是一樣的啊!

    showname.sh 在父程序當中運作的示意圖
    圖12.2.2、showname.sh 在父程序當中運作的示意圖
  • 相关阅读:
    bootstrap学习笔记一: bootstrap初认识,hello bootstrap(下)
    bootstrap学习笔记一: bootstrap初认识,hello bootstrap(上)
    AutoCompleteTextView的使用
    常用的android弹出对话框
    PopupWindow的使用
    linux udev、mdev 介绍
    linux 守护进程编程
    linux 下的文件目录操作之遍历目录
    linux 下查找图片文件方法
    linux 内核 zImage 生成过程分析
  • 原文地址:https://www.cnblogs.com/-wanglei/p/10063171.html
Copyright © 2011-2022 走看看