P370

  • 情境模拟题一:透过 grep 搜寻特殊字串,并配合数据流重导向来处理大量的文件搜寻问题。

    • 目标:正确的使用正规表示法;
    • 前提:需要了解数据流重导向,以及透过子命令 $(command) 来处理档名的搜寻;

    我们简单的以搜寻星号 (*) 来处理底下的任务:

    1. 利用正规表示法找出系统中含有某些特殊关键字的文件,举例来说,找出在 /etc 底下含有星号 (*) 的文件与内容:

      解决的方法必须要搭配万用字节,但是星号本身就是正规表示法的字符,因此需要如此进行:

      [root@www ~]# grep '\*' /etc/*
      

      你必须要注意的是,在单引号内的星号是正规表示法的字符,但我们要找的是星号,因此需要加上跳脱字符 (\)。但是在 /etc/* 的那个 * 则是 bash 的万用字节! 代表的是文件的档名喔!不过由上述的这个结果中,我们仅能找到 /etc 底下第一层子目录的数据,无法找到次目录的数据, 如果想要连同完整的 /etc 次目录数据,就得要这样做:

      [root@www ~]# grep '\*' $(find /etc -type f)
      
    2. 但如果文件数量太多呢?如同上述的案例,如果要找的是全系统 (/) 呢?你可以这样做:
      [root@www ~]# grep '\*' $(find / -type f)
      -bash: /bin/grep: Argument list too long
      

      真要命!由於命令列的内容长度是有限制的,因此当搜寻的对象是整个系统时,上述的命令会发生错误。那该如何是好? 此时我们可以透过管线命令以及 xargs 来处理。举例来说,让 grep 每次仅能处理 10 个档名,此时你可以这样想:

      1. 先用 find 去找出文件;
      2. 用 xargs 将这些文件每次丢 10 个给 grep 来作为参数处理;
      3. grep 实际开始搜寻文件内容。

      所以整个作法就会变成这样:

      [root@www ~]# find / -type f | xargs -n 10 grep '\*'
      
    3. 从输出的结果来看,数据量实在非常庞大!那如果我只是想要知道档名而已呢?你可以透过 grep 的功能来找到如下的参数!
      [root@www ~]# find / -type f | xargs -n 10 grep -l '\*'
      
  • 情境模拟题二:使用管线命令配合正规表示法创建新命令与新变量。我想要创建一个新的命令名为 myip , 这个命令能够将我系统的 IP 捉出来显示。而我想要有个新变量,变量名为 MYIP ,这个变量可以记录我的 IP 。

    处理的方式很简单,我们可以这样试看看:

    1. 首先,我们依据本章内的 ifconfig, sed 与 awk 来取得我们的 IP ,命令为:

      [root@www ~]# ifconfig eth0 | grep 'inet addr' | \
      >  sed 's/^.*inet addr://g'| cut -d ' ' -f1
      
    2. 再来,我们可以将此命令利用 alias 指定为 myip 喔!如下所示:
      [root@www ~]# alias myip="ifconfig eth0 | grep 'inet addr' | \
      >  sed 's/^.*inet addr://g'| cut -d ' ' -f1 "
      
    3. 最终,我们可以透过变量配置来处理 MYIP 喔!
      [root@www ~]# MYIP=$( myip )
      
    4. 如果每次登陆都要生效,可以将 alias 与 MYIP 的配置那两行,写入你的 ~/.bashrc 即可!
script 的运行方式差异 (source, sh script, ./script)
利用直接运行的方式来运行 script

这个脚本可以让使用者自行配置两个变量,分别是 firstname 与 lastname,想一想,如果你直接运行该命令时,该命令帮你配置的 firstname 会不会生效?看一下底下的运行结果:

[root@www scripts]# echo $firstname $lastname<==确认了,这两个变量并不存在喔!
[root@www scripts]# sh sh02.sh
Please input your first name: VBird <==这个名字是鸟哥自己输入的
Please input your last name:  Tsai Your full name is: VBird Tsai      <==看吧!在 script 运行中,这两个变量有生效
[root@www scripts]# echo $firstname $lastname<==事实上,这两个变量在父程序的 bash 中还是不存在的!

上面的结果你应该会觉得很奇怪,怎么我已经利用 sh02.sh 配置好的变量竟然在 bash 环境底下无效!怎么回事呢? 如果将程序相关性绘制成图的话,我们以下图来说明。当你使用直接运行的方法来处理时,系统会给予一支新的 bash 让我们来运行 sh02.sh 里面的命令,因此你的 firstname, lastname 等变量其实是在下图中的子程序 bash 内运行的。 当 sh02.sh 运行完毕后,子程序 bash 内的所有数据便被移除,因此上表的练习中,在父程序底下 echo $firstname 时, 就看不到任何东西了!这样可以理解吗?


图 2.2.1、sh02.sh 在子程序中运行


  • 利用 source 来运行脚本:在父程序中运行

如果你使用 source 来运行命令那就不一样了!同样的脚本我们来运行看看:

[root@www scripts]# source sh02.sh
Please input your first name: VBird
Please input your last name:  TsaiYour full name is: VBird Tsai
[root@www scripts]# echo $firstname $lastname
VBird Tsai  <==嘿嘿!有数据产生喔!

竟然生效了!没错啊!因为 source 对 script 的运行方式可以使用底下的图示来说明! sh02.sh 会在父程序中运行的,因此各项动作都会在原本的 bash 内生效!这也是为啥你不注销系统而要让某些写入 ~/.bashrc 的配置生效时,需要使用『 source ~/.bashrc 』而不能使用『 bash ~/.bashrc 』是一样的啊!


图 2.2.2、sh02.sh 在父程序中运行

利用 test 命令的测试功能

当我要检测系统上面某些文件或者是相关的属性时,利用 test 这个命令来工作真是好用得不得了, 举例来说,我要检查 /dmtsai 是否存在时,使用:

[root@www ~]# test -e /dmtsai

运行结果并不会显示任何信息,但最后我们可以透过 $? 或 && 及 || 来展现整个结果呢! 例如我们在将上面的例子改写成这样:

[root@www ~]# test -e /dmtsai && echo "exist" || echo "Not exist"
Not exist  <==结果显示不存在啊!

利用判断符号 [ ]

如果我想要知道 $HOME 这个变量是否为空的,可以这样做:

[root@www ~]# [ -z "$HOME" ] ; echo $?

使用中括号必须要特别注意,因为中括号用在很多地方,包括万用字节与正规表示法等等,所以如果要在 bash 的语法当中使用中括号作为 shell 的判断式时,必须要注意中括号的两端需要有空白字节来分隔喔! 假设我空白键使用『□』符号来表示,那么,在这些地方你都需要有空白键:

[  "$HOME"  ==  "$MAIL"  ]
[□"$HOME"□==□"$MAIL"□]↑       ↑  ↑       ↑
Tips:
你会发现鸟哥在上面的判断式当中使用了两个等号『 == 』。其实在 bash 当中使用一个等号与两个等号的结果是一样的! 不过在一般惯用程序的写法中,一个等号代表『变量的配置』,两个等号则是代表『逻辑判断 (是否之意)』。 由於我们在中括号内重点在於『判断』而非『配置变量』,因此鸟哥建议您还是使用两个等号较佳!

上面的例子在说明,两个字串 $HOME 与 $MAIL 是否相同的意思,相当於 test $HOME = $MAIL 的意思啦! 而如果没有空白分隔,例如 [$HOME==$MAIL] 时,我们的 bash 就会显示错误信息了!这可要很注意啊! 所以说,你最好要注意:

  • 在中括号 [] 内的每个组件都需要有空白键来分隔;
  • 在中括号内的变量,最好都以双引号括号起来;
  • 在中括号内的常数,最好都以单或双引号括号起来。

为什么要这么麻烦啊?直接举例来说,假如我配置了 name="VBird Tsai" ,然后这样判定:

[root@www ~]# name="VBird Tsai"
[root@www ~]# [ $name == "VBird" ]
bash: [: too many arguments

见鬼了!怎么会发生错误啊?bash 还跟我说错误是由於『太多参数 (arguments)』所致! 为什么呢?因为 $name 如果没有使用双引号刮起来,那么上面的判定式会变成:

[ VBird Tsai == "VBird" ]

Shell script 的默认变量($0, $1...)

我们知道命令可以带有选项与参数,例如 ls -la 可以察看包含隐藏档的所有属性与权限。那么 shell script 能不能在脚本档名后面带有参数呢?很有趣喔!举例来说,如果你想要重新启动系统登录档的功能,可以这样做:

[root@www ~]# file /etc/init.d/syslog
/etc/init.d/syslog: Bourne-Again shell script text executable
# 使用 file 来查询后,系统告知这个文件是个 bash 的可运行 script 喔!
[root@www ~]# /etc/init.d/syslog restart

restart 是重新启动的意思,上面的命令可以『重新启动 /etc/init.d/syslog 这支程序』的意思! 唔!那么如果你在 /etc/init.d/syslog 后面加上 stop 呢?没错!就可以直接关闭该服务了!这么神奇啊? 没错啊!如果你要依据程序的运行给予一些变量去进行不同的任务时,本章一开始是使用 read 的功能!但 read 功能的问题是你得要手动由键盘输入一些判断式。如果透过命令后面接参数, 那么一个命令就能够处理完毕而不需要手动再次输入一些变量行为!这样下达命令会比较简单方便啦!

script 是怎么达成这个功能的呢?其实 script 针对参数已经有配置好一些变量名称了!对应如下:

/path/to/scriptname  opt1  opt2  opt3  opt4 $0             $1    $2    $3    $4

这样够清楚了吧?运行的脚本档名为 $0 这个变量,第一个接的参数就是 $1 啊~ 所以,只要我们在 script 里面善用 $1 的话,就可以很简单的立即下达某些命令功能了!除了这些数字的变量之外, 我们还有一些较为特殊的变量可以在 script 内使用来呼叫这些参数喔!

  • $# :代表后接的参数『个数』,以上表为例这里显示为『 4 』;
  • $@ :代表『 "$1" "$2" "$3" "$4" 』之意,每个变量是独立的(用双引号括起来);
  • $* :代表『 "$1c$2c$3c$4" 』,其中 c 为分隔字节,默认为空白键, 所以本例中代表『 "$1 $2 $3 $4" 』之意。

那个 $@ 与 $* 基本上还是有所不同啦!不过,一般使用情况下可以直接记忆 $@ 即可! 好了,来做个例子吧~假设我要运行一个可以携带参数的 script ,运行该脚本后萤幕会显示如下的数据:

  • 程序的档名为何?
  • 共有几个参数?
  • 若参数的个数小於 2 则告知使用者参数数量太少
  • 全部的参数内容为何?
  • 第一个参数为何?
  • 第二个参数为何
[root@www scripts]# vi sh07.sh
#!/bin/bash
# Program:
#   Program shows the script name, parameters...
# History:
# 2009/02/17    VBird   First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATHecho "The script name is        ==> $0"
echo "Total parameter number is ==> $#"
[ "$#" -lt 2 ] && echo "The number of parameter is less than 2.  Stop here." \&& exit 0
echo "Your whole parameter is   ==> '$@'"
echo "The 1st parameter         ==> $1"
echo "The 2nd parameter         ==> $2"

运行结果如下:

[root@www scripts]# sh sh07.sh theone haha quot
The script name is        ==> sh07.sh            <==档名
Total parameter number is ==> 3                  <==果然有三个参数
Your whole parameter is   ==> 'theone haha quot' <==参数的内容全部
The 1st parameter         ==> theone             <==第一个参数
The 2nd parameter         ==> haha               <==第二个参数

  • shift:造成参数变量号码偏移

除此之外,脚本后面所接的变量是否能够进行偏移 (shift) 呢?什么是偏移啊?我们直接以底下的范例来说明好了, 用范例说明比较好解释!我们将 sh07.sh 的内容稍作变化一下,用来显示每次偏移后参数的变化情况:

[root@www scripts]# vi sh08.sh
#!/bin/bash
# Program:
#   Program shows the effect of shift function.
# History:
# 2009/02/17    VBird   First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATHecho "Total parameter number is ==> $#"
echo "Your whole parameter is   ==> '$@'"
shift   # 进行第一次『一个变量的 shift 』
echo "Total parameter number is ==> $#"
echo "Your whole parameter is   ==> '$@'"
shift 3 # 进行第二次『三个变量的 shift 』
echo "Total parameter number is ==> $#"
echo "Your whole parameter is   ==> '$@'"

这玩意的运行成果如下:

[root@www scripts]# sh sh08.sh one two three four five six <==给予六个参数
Total parameter number is ==> 6   <==最原始的参数变量情况
Your whole parameter is   ==> 'one two three four five six'
Total parameter number is ==> 5   <==第一次偏移,看底下发现第一个 one 不见了
Your whole parameter is   ==> 'two three four five six'
Total parameter number is ==> 2   <==第二次偏移掉三个,two three four 不见了
Your whole parameter is   ==> 'five six'
  • 单层、简单条件判断式

如果你只有一个判断式要进行,那么我们可以简单的这样看:

if [ 条件判断式 ]; then当条件判断式成立时,可以进行的命令工作内容;
fi   <==将 if 反过来写,就成为 fi 啦!结束 if 之意!

date_d=$(echo $date2 |grep '[0-9]\{8\}')   # 看看是否有八个数字
if [ "$date_d" == "" ]; then
echo "You input the wrong date format...."
exit 1
fi

找出2-5个o的连续字符串,因为{与}的符号在shell是有特殊意义,因此,必须要用转义字符\来让它失去特殊意义

grep -n 'o\{2\}' regular_express.txt

利用 case ..... esac 判断

case  $变量名称 in   <==关键字为 case ,还有变量前有钱字号"第一个变量内容")   <==每个变量内容建议用双引号括起来,关键字则为小括号 )程序段;;            <==每个类别结尾使用两个连续的分号来处理!"第二个变量内容")程序段;;*)                  <==最后一个变量内容都会用 * 来代表所有其他值不包含第一个变量内容与第二个变量内容的其他程序运行段exit 1;;
esac                  <==最终的 case 结尾!『反过来写』思考一下!

利用 function 功能

什么是『函数 (function)』功能啊?简单的说,其实, 函数可以在 shell script 当中做出一个类似自订运行命令的东西,最大的功能是, 可以简化我们很多的程序码~举例来说,上面的 sh12.sh 当中,每个输入结果 one, two, three 其实输出的内容都一样啊~那么我就可以使用 function 来简化了! function 的语法是这样的:

function fname() {程序段
}

function 也是拥有内建变量的~他的内建变量与 shell script 很类似, 函数名称代表示 $0 ,而后续接的变量也是以 $1, $2... 来取代的~ 这里很容易搞错喔~因为『 function fname() { 程序段 } 』内的 $0, $1... 等等与 shell script 的 $0 是不同的。以上面 sh12-2.sh 来说,假如我下达:『 sh sh12-2.sh one 』 这表示在 shell script 内的 $1 为 "one" 这个字串。但是在 printit() 内的 $1 则与这个 one 无关。 我们将上面的例子再次的改写一下,让你更清楚!

[root@www scripts]# vi sh12-3.sh
#!/bin/bash
# Program:
#   Use function to repeat information.
# History:
# 2005/08/29    VBird   First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATHfunction printit(){echo "Your choice is $1"   # 这个 $1 必须要参考底下命令的下达
}echo "This program will print your selection !"
case $1 in"one")printit 1  # 请注意, printit 命令后面还有接参数!;;"two")printit 2;;"three")printit 3;;*)echo "Usage $0 {one|two|three}";;
esac

在上面的例子当中,如果你输入『 sh sh12-3.sh one 』就会出现『 Your choice is 1 』的字样~ 为什么是 1 呢?因为在程序段落当中,我们是写了『 printit 1 』那个 1 就会成为 function 当中的 $1 喔~

while do done, until do done (不定回圈)

一般来说,不定回圈最常见的就是底下这两种状态了:

while [ condition ]  <==中括号内的状态就是判断式
do            <==do 是回圈的开始!程序段落
done          <==done 是回圈的结束

while 的中文是『当....时』,所以,这种方式说的是『当 condition 条件成立时,就进行回圈,直到 condition 的条件不成立才停止』的意思。还有另外一种不定回圈的方式:

until [ condition ]
do程序段落
done

for...do...done (固定回圈)

相对於 while, until 的回圈方式是必须要『符合某个条件』的状态, for 这种语法,则是『 已经知道要进行几次回圈』的状态!他的语法是:

for var in con1 con2 con3 ...
do程序段
done

转载于:https://www.cnblogs.com/jonathanyue/p/9301297.html

鸟哥的linux私房菜学习笔记7相关推荐

  1. 鸟哥的linux私房菜运维篇,鸟哥的Linux私房菜学习笔记之SAMBA

    鸟哥的Linux私房菜学习笔记之SAMBA 发布时间:2020-06-24 01:44:50 来源:51CTO 阅读:185 作者:tomshen NFS仅能让Unix/linux之间共享数据,CIF ...

  2. 鸟哥的Linux私房菜学习笔记(2)登录与在线求助

    以管理员身份运行VMware Player,点击之前安装好的CentOS 7版本的虚拟机,会出现以下界面:  这是我建立的一般账户,ROOT由于身份比较特殊,所以没有被列出来.  点击 "未 ...

  3. 鸟哥linux群,【鸟哥的linux私房菜-学习笔记】linux的帐号与群组

    linux的帐号与群组 使用者标识符: UID 与 GID ID 与账号的对应就在 /etc/passwd 当中: 计算机只认得ID(即数字),并不能区别账号: 每个登陆的使用者至少都会取得两个 ID ...

  4. 鸟哥的linux私房菜学习笔记《二十》bash简介

    shell的功能: 提供用户操作系统的一个接口. 系统上合法的shell要写在/etc/shells这个文件,因为系统某些服务在运行过程中会去检查用户能够使用的shells,而这些shell的查询就是 ...

  5. Linux管道命令——《鸟哥的Linux私房菜》笔记

    Linux管道命令--<鸟哥的Linux私房菜>笔记 0 前言 看完书之后,总感觉不记录下来的话,很快就会忘了,然后又需要重新到处翻书找资料,所以还是把内容记录下来,方便以后复习.本文大部 ...

  6. 鸟哥的Linux私房菜学习心得-基础操作

    <鸟哥的Linux私房菜>特别适合新手作为Linux的入门教材,即使没有计算机知识基础也能学明白,鸟哥算是很用心了.半个月来学习了鸟哥主页教程的基础篇,感觉良好,因此特意写下学习的感受,以 ...

  7. 鸟哥的 Linux 私房菜学习总结(超赞!!!)

    我是技术搬运工,好东西当然要和大家分享啦.原文地址 常用操作以及概念 求助 1. --help 指令的基本用法与选项介绍. 2. man man 是 manual 的缩写,将指令的具体信息显示出来. ...

  8. 鸟哥的Linux私房菜读书笔记:Linux磁盘与文件系统管理

    系统管理员很重要的任务之一就是管理好自己的磁盘文件系统, 每个分区不可太大也不能太小, 太大会造成磁盘容量的浪费, 太小则会产生文件无法储存的困扰. 前面谈到的文件权限与属性中, 这些权限与属性分别记 ...

  9. 鸟哥的Linux私房菜 读书笔记

    个人表示,每次看电子档,都会从头开始读,话说会一直读不完.以前会有手抄板的读书笔记,但是不方便携带.现在就开始电子档的读书笔记吧. 1. Kernel 必须管理的事项有: * 系统呼叫接口(syste ...

  10. 鸟哥的Linux私房菜 命令笔记2

    which:寻找执行档 which [-a] command -a:all将所有从$PATH目录中可以找到的指令均列出来,而不止第一个被找到的指令名称 which ifconfig which whi ...

最新文章

  1. 它是谁?一个比 c3p0 快200倍的数据库连接池!
  2. 波士顿动力机器狗量产版首次亮相:先造100台,能当警犬能工地巡逻
  3. 工信部支持的项目接单平台,团队、公司请进
  4. How Kyma plugin register hook to Activate and deactivate event
  5. mysql查询优化之一:mysql查询优化常用方式
  6. 了解 Adobe Scout 收集和使用的数据
  7. 这位顶会领域主席的论文被自己的AI审稿系统拒绝了
  8. Bailian2687 数组逆序重放【逆序处理】
  9. 数据库树形结构,EasyUI Tree 树
  10. JS学习总结(2)——变量
  11. echarts设置之stack参数
  12. 揭秘ServerBootstrap神秘面纱(服务端ServerBootstrap)
  13. FPGA实验2:ADDA测试
  14. 转专业2017武汉大学计算机学,武大,10届考生谈谈转专业~`~
  15. AppleScript+JavaScript自动认证校园网
  16. Gym - 101350E - Competitive Seagulls (博弈)
  17. javaScript打气球小游戏
  18. python中len 函数_python len
  19. Windows下WinRar创建自解压文件
  20. movielens数据集下载

热门文章

  1. dell服务器全系列手册,DELL服务器 RAID配置中文手册.pdf
  2. ajax怎么会突然出现401,当jquery ajax遇上401请求
  3. 毕业即失业,转行软件测试的辛酸泪只有自己知道
  4. BinaryOperator示例
  5. 思念绵绵,爱在彼此心间漫延
  6. Cadence导出Excel格式BOM表
  7. ubuntu中firfox插件xmarks的同步问题
  8. zui消息推送服务器,ZUI
  9. ffmpeg去除视频黑边命令
  10. qq企业邮箱的发送邮件服务器地址,腾讯企业邮箱smtp发邮件