8月5日课堂笔记

bash基础及shell编程初步

bash的特性及bash脚本编程初步

   操作系统硬件, 内核把底层硬件的复杂性给隐藏起来,统一输出为一种系统调用,系统调用非常底层,把系统调用封装成了库。让程序运行起来。用户在创建时有一个默认shell。终点设备用来当做标准输入和输出。

 要想与主机交互,需要一个【终端】,附着在终端接口程序:
    CUI:KDE,GNome,XFce 
    CLI:/etc/shells
    bash
    zsh
    fish

接口和计算机打交道非常重要

bash的特性:
   命令行展开:~,{}
   命令别名:alias,unalias
   命令历史:history
   文件名通配:glob
   快捷键:ctrl+a,e,u,k,l
   命令补全:$PATH 
   路径补全:用户指定的起始位置下查找的

bash特性之:命令hash

   缓存此前命令的查找结果:key-value(见直数据)
      key:搜索键
      value:值

   hash命令:
      hash:列出
      hash -d COMMAND:删除
      hash -r :清空

bash的特征之:变量

程序:指令+数据     

指令:由程序文件提供;

数据:可以通过标准输入IO设备、文件、管道、变量(读出的数据加工很多遍) 不会对源文件进行修改。文件,程序在CPU上运行,只能通过内存不断加载指令,并对数据完成加工操作。从文件中copy一行出来,暂存在内存中某个位置,内存中指定位置的数据,由cpu运行的指令,完成字符改写。改完后保存在内存中的另外一个位置。保存后输出到IO设备上。接下来第二行数据读出来,还保存在同样的内存空间中,内存上的数据要不断变化,将来cpu上的指令要不断的引用这段内存上的数据。为了便于引用这段内存上的数据,取个名字叫变量。变量名称是指向一个内存空间的,这个变量的名称会不断地发生变化,这就叫变量。

一个名字引用所有变量的值:数组。就是在一个大的内存空间中取一个名,其内部又被分成每一个逻辑单元,一个逻辑单元叫一个元素。同类元素,取同一个名称,保存到一个内存空间中,叫数组。

数组也是变量,是一串连续的变量。

程序:算法+数据结构

算法:解决问题的路径,过程需要依赖

变量名+指向的内存空间

变量名:指向内存空间中的某一空间的起止地址,在那一段空间中,我们就可以存储数据

变量赋值:把我们要存储的数据,存储到变量名所指向的内存空间的过程。

shell变量赋值的方式:name=value 名称=值 字符串存到了名称所指向的内存空间中去了

变量类型:存储格式、表示数据范围、参与的运算

变量值的存储类型;

字符串相加123,34 =12334 数值相加123,34=157

编程语言:
强类型变量:c
弱类型变量:

bash把所有变量统统视作字符型;

bash中的变量无需事先声明;相当于把声明和赋值过程同时实现 声明:类型,变量名 num1=123,str1=34 强类型中不被允许

弱类型:自动把字符串转换成数值,或者反过来

变量替换:把变量名出现的位置替换为其所指向的内存空间中的数据;

变量引用:把变量名出现的位置替换${varname},$varname

特性:1、把所有变量都视作字符型 2、bash中的变量无需事先声明,直接使用

    变量名:变量名只能包含数字、字母和下划线,不能以数字开头;
        变量名:见名知义,命名机制遵循某种法则;不能使用程序的保留字,例如if,else,then,while

  bash变量类型:

根据作用范围划分: 本地变量:作用域仅为当前shall进程 环境变量:作用域当前shell进程及子进程,同级没影响 局部变量:作用域仅为某代码片段(函数上下文)

linux是一个多用户的操作系统,系统运行时多个用户登录进来,每个用户都需要一个终端,每一个终端上就应该有一个接口,接口程序中最常见的就是CLI接口,CLI接口对应的就是shell进程,事实上默认的bash在用户一登录,我们系统就启动一个bash进程来随时响应用户的请求。命令提示符信息就是又一个shell的进程显示的,多个用户登录就意味着多个shell进程。shell进程之间是各自独立的,每一个shell进程都有生命周期,各自独立的概念,同级shell。在一个shell进程下,可以嵌套一个shell进程,shell类型也可以不一样

 位置参数变量:向执行脚本的shell进程传递的参数
 特殊变量:shell内置的有特殊功能的变量:
    $?:上一个命令的执行状态结果保存在特殊变量中
    0:成功
    1-255:失败

定义方式
本地变量: 变量赋值:name=value 变量引用:${name},$name '',变量名不会替换为其值 "",变量名会替换为其值

查看变量:set

撤销变量:unset name(变量名)
     注意:此处非变量引用,不能使用$

环境变量:
    变量赋值:
     (1) export name=value
     (2) name=value
           export name
     (3) declare -x name=value
     (4) name=value
           declare -x name
   变量引用:$(name),$name

   注意:bash内嵌了许多环境变量(通常为全大写字符),用于定义bash的工作环境
   PATH,HISTFILE,HISTSIZE,HISTFILESIZE,HISTCONTROL,PWD,UID,HOME,SHELL,OLDPWD

   查看环境变量:export,declare -x,printenv,env
   撤销环境变量:unset name
       注意:只加name,不加$

只读变量:不能修改和不能取消 (1)declare -r name (2)readonly name

  只读变量无法重新赋值,并且不支持撤销;存活时间为当前shell进程的生命周期,随shell进程的终止而终止

bash特性之多命令执行: ~]# COMMAND1;COMMAND2;COMMAND3; 一行多个命令

 逻辑运算:
   运算数:真(true,yes,on,1)
           假(false,no,off,0)

   与:
     1 && 1=1 
     1 && 0=0 
     0 && 1=0  
     0 && 0=0
   或:
      1 || 0 =1
      1 || 1 =1
      0 || 1 =1
      0 || 0 =0        
   非:
      ! 1 =0
      ! 0 =1

短路法则:
~]# COMMAND1 && COMMAND
    两个命令的执行状态结果做出&运算
       COMMAND1为假,则COMMAND2不会再执行;
    否则:COMMAND1为真,则COMMAND2必须执行;

 ~]# COMMAND1 || COMMAND2
      COMMAND1为真,则COMMAND2不会再执行;
      否则:COMMAND1为假,则COMMAND2必须执行;

 ~]# id  $username  || useradd $username

shell脚本编程: 编程语言的分类:根据运行方式 编译运行:源代码–>编译器(编译)–>程序文件 然后运行程序文件(运行速度更快,需要先编译,有bug,先修改源代码,再编译,才能运行。后来出现了项目管理工具,能够将一个源代码文件切割成放置在n个文件中,导致某一个文件可以独立编译,单独编译错误的地方) c语言:所写出来的源代码,编程成指定的二进制文件也有可能是库文件,调用函数库的函数来实现独立完成,无需调用外部的其他程序

   解释运行:源代码-->运行时启动解释器,由解释器边解释边运行;源代码本身并不运行,运行一个解释器进程,把源代码的内容当作解释器要运行的程序。解释运行
   万一发现错误,仅需要修改源代码,在进行解释运行

都需要一个翻译官

 脚本编程是完全借助于外部的程序来完成

根据其编程过程中功能的实现是调用库还是调用外部的程序文件:
    shell脚本编程:
      利用系统上的命令及编程组件进行编程;

    完整编程:
      利用库或编程组件进行编程
      程序员不需要操作系统上必须存在某个命令,自己通过库或者自己所写的代码来完成所有操作

  根据编程模型分类
     过程式编程语言:
     面向对象的编程语言:    

  程序=指令+数据
      过程式:以指令为中心来组织代码,数据是服务于代码;
       顺序执行
       选择执行
       循环执行

      过程式代表:c语言,bash

      对象式:以数据为中心来组织代码,围绕指数据来组织指令;
        类(class):实例化对象,method;
     首先程序员要写很多类,每一个类当中包含的数据结构或者称实例化出来的数据对象,对这个对象要施加哪些操作,

       对象式代表:java,c++,python

 shell脚本编程:过程式编程,解释运行,依赖于外部程序文件运行;可以多个命令一遍运行出来。

   如何写shell脚本:
       脚本文件的第一行,顶格:给树shebang,解释器路径,用于指明解释执行当前脚本的解释器程序文件
           常见的解释器:
              #!/bin/bash
              #!/user/bin/python
              #!/user/bin/perl

        文本编辑器:nano 
            行编辑器:sed
            全屏幕编辑:nano,vi,vim

       shell脚本是什么?
           命令的堆积;
           但很多命令不具有幂等性,需要用程序逻辑来判断运行条件是否满足,以避免其运行中发生错误;

        运行脚本:
          (1)赋予执行权限,并直接运行此程序文件;
                chmod+x /RATH/TO/SCRIPT_FILE
                ./PATH/TO/SCRIPT_FILE

           (2)直接运行解释器,将脚本以命令行参数传递给解释器程序
               bash /PATH/TO/SCRIPT_FILE

       注意:脚本中的空白行会被解释器忽略
             脚本中,除了shebang,余下所有以#开头的行,都会被视作注释行而被忽略;此即为注释行;
             shell脚本的运行是通过运行一个子shell进程实现的

练习1:写一个脚本,实现如下功能; (1)显示/etc下目录下所有以大写p或小写p开头的文件或目录本身 (2)显示/var目录下的所有文件或目录本身,并将显示结果中的小写字母转换为大写后显示; (3)创建临时文件/tmp/mtfile.xxxx;

#!/bin/bash ls -d /etv/[pP]* ls -d /var/* |tr [a-z] [A-Z] mktemp /tmp/myfile.xxxx

bash的配置文件: 两类: profile类:为交互式登录的shell进程提供配置 bashrc类:为非交互式登录的shell进程提供配置

登录类型: 交互式登录shell进程: 直接通过某终端输入账号和密码后登录打开的shell进程; 使用su命令:su -USERNAME,或者使用su- |username的登录切换;

    非交互式登录shell进程;
        su username执行的登录切换;
        图形界面下打开的终端;
        运行脚本


  profile类:
      全局:对所有用户都生效;
        /etc/profile
        /etc/profild.l/*.sh

      用户个人:仅对当前用户有效;
          ~/.bash_profile

   功用:
       1、用于定义环境变量;
       2、运行命令或脚本;


  bashre类:
     全局:
        /etc/bashrc

      用户个人:
         ~/.bashrc

    功用:
        1、定义本地变量;
        2、定义命令别名;

  注意:仅管理员可修改全局配置文件;

    交互式登录shell进程:
        /etc/profile -->/etc/profile.d/* --> ~/.bash_profile
        -->~/.bashre -->etc/bashrc

     非交互式登录shell进程:
       ~/.bashrc -->etc/bashrc-->/etc/profile.d/*

    命令行中定义的特性,例如变量和别名作用域为当前shell进程的生命周期;
    配置文件定义的特性,只对随后新启动的shell进程有效;

    .命令
    让通过配置文件定义的特性立即生效:
        (1)通过命令行重新定义一次;
        (2)让shell进程重读配置文件;
             ~]#source /PATH/FROM/CONF_FILE
             ~]#./PATH/FRON/CONF_FILE

正则表达式与grep

回顾:hash、变量、shell的脚本编程 bash的特性:hash,变量 命令hash:此前查找的命令结果给缓存起来 ,并且再次执行时使得其执行性能更好。保存方式:hash命令

     变量类型:
        本地变量,环境变量,局部变量
        位置参数变量,特殊变量

      变量的赋值方式:name=value
          环境变量使用:export name=value
                   declare -x  name =value

      变量引用:$name,$(name)  
      撤销:unset name

bash脚本编程的简单实现,运行脚本 #!/bin/bash #开头和空白行都会被忽略

bash的配置文件 profile类:登录式shell
su – 终端

   bashrc类:非登录式shell
     图形界面下的窗口


  登录式shell:读得次序
     /etc/profile -->etc/profile.d/*.sh--> -/.bash_profile--> -/.bashrc -->/etc/bashrc

  非登录式shell:~/.bashrc -->etc/bashrc -->etc/profile.d/*.sh

profile类的配置文件主要是用来实现定义环境变量或定义运行的命令或脚本。 bashrc类的配置文件主要用来定义本地变量和命令别名

抽取文本的工具: 查看文件内存:cat -n:显示行号,空行也加行号 -b:显示行号,忽略空行 -ns:显示行号,压缩空行,相邻的空行可以压缩掉 -v:能看到^M -A:显示所有

    more:分页查看文件
      more [option..]  FILE..
        -d:显示翻页及退出提示

    less:可以上下翻页
          搜索关键字

    head:
       head [option]..[file..]
          -c #:指定获取前#字节
          -n #:指定获取前#行
          -#: 指定行

    tail:
       tail [option]..[file]..
            -c #:指定获取后#字节
            -n #:指定获取后#行
            -#:
            -f:跟踪显示文件新追加的内容,常用日志监控

     要求:自动显示新日志,不影响日常工作 

    tail -n 0 -f /var/log/messages &

按列抽取文本cut和合并文件paste cut [option] .. [file] … -d DELIMITER:指明分隔符,默认tob -f FILEDS: 例如cut -d: -f1,2,3 文件名 #:第#个字段 #,#[,#]:离散的多个字段,例如1,3,6 #-#:连续的多个字段,例如1-6 混合使用:1-3,7 -c :按字符切割 –output-delimiter=STRING指定输出分隔符 例如cut -d:f1,3 –output-delimiter=" " 文件名

       显示文件或STDIN数据的指定列
        cut -d:-f1 /etc/passwd
        cat /etc/passwd | cut -d : -f7
        cut -c2-5 /usr/share/dict/words

      paste [option]..[file]..
        -d 分隔符:指定分隔符,默认用TAB
        -s:所有行合成一行显示
        paste f1 f2
        paste -s f1 f2

分析文本的工具 收集文本统计数据wc 计数单词总数、行总数、字节总数和字符总数 可以对文件或STDIN中的数据预习 $ wc story/txt 39 237 1901 story.txt 行数 字数 字符数

  使用  -l 来只计数行数
  使用  -w 来只计数单词总数
  使用  -c 来只计数字节总数
  使用  -m 来只计数字符总数

文本排序sort 把整理过的文本显示在STDOUT,不改变原始文件 $ sort [option] file(s)

常用选项
-r:执行反方向(由上至下)整理
-n:执行按数字大小整理
-f:选项忽略(fold)字符串中的字符大小写
-u:选项(独特,unique)删除输出中的重复行
-t c :选项使用c做为字段界定符
-k X :选项按照使用c字符分隔的X列来整理能够使用多次
   例如:sort -t: -k2 -n  以冒号为分隔符,第二列,按数字大小排序

文本处理工具:

linux上文本处理三剑客: grep:文本过滤工具(模式:pattern)工具; grep:基本正则表达式,-E支持扩展正则表达式 egrep:支持扩展正则表达式,-G表示支持基本正则表达式 fgrep:不支持正则表达式,-E扩展,-G基本 sed:stream editor,流编辑器;文本编辑工具; awk:linux上的实现为gawk,文本报告生成器(格式化文本);

重点中的重点: 正则表达式:Regual Expression ,简写REGEXP 由一类特殊字符及文本字符所编写的模式,其中有些字符不表示其字面意义,而是用于表示控制或通配的功能; 分两类: 基本正则表达式:BRE 扩展正则表达式:ERE

      元字符:正则表达式的元字符

    匹配单词\(hello[[:space:]]\+\)\+  都有特殊的功用和意义

之所以计算机有只能功能,正则表达式的出现立下汗马功劳,因为正则表达式能分析目录并查找符合条件的文本。 计算机中的数据,文本数据,数字数据。处理工具智能化。

 grep工具:
   global search regular expression and print out the line
会全文搜索每一行,根据用户所给定的格式来过滤,再每一行执行相应的解锁工作,如果某一行能被模式匹配到,则把这一行显示出来

  作用:文本搜索工具,根据用户指定的“模式(过滤条件)”对目标文本进行匹配检查;打印匹配到的行;

   模式:由正则表达式的元字符及文本字符编写出的过滤条件;

   每一个正则表达式模式的实现或者称能够搜索正则表达式模式
   的实现都要用到正则表达式引擎;

   正则表达式引擎:

   grep [options] PATERN [FILE..]
   grep [OPTIONS] [-e PATTERN | -f FILE] [FILE...]

例如:grep "UUID" /etc/fstab OPTIIONS: –color=auto;对匹配到的文本做着色后高亮显示; -i:ignorecase;忽略字符大写小写; -o:仅显示匹配到的字符串本身; -v:反向匹配;显示不能被模式匹配到的行; -E:支持使用扩展的正则表达式元字符; -q:–quiet,–silent:静默模式,即不输出任何信息;

    -A #:after,后#行
    -B #:before,前#行 
    -C #:context,前后各#行

  基本正则表达式的元字符:
     字符匹配:
         .   :匹配任意单个字符
          grep "r..t" /etc/fstab 
         []  :匹配指定范围内的任意单个字符
          grep "r[[:alpha:]][[:alpha:]]t" /etc/fstab
         [^] :匹配指定范围外的任意单个字符;
             [:digit:],[:lower:],[:upper:],[:alpha:],[:alnum:],[:punct:],[:space:]

            grep "roo[[:digit:]]" /ets/fstab


     匹配次数:用在要指定其出现的次数的字符的后面,用于限制其前面字符出现的次数;默认工作于贪婪模式;
        *:匹配其前面的字符任意次;0,1,多次;
              例如:grep "x"*"y"

        .*:匹配任意长度的任意字符
        \?:匹配前面的字符0或1次;即其前面的字符是可有可无的;
        \+:匹配其前面的字符1次或多次;及其前面的字符至少要出现一次;
        \{m\}:匹配其前面的字符m次;
        \{m,n}:匹配其前面的字符至少m次,至多n次
            \{0,n\}:至多n次
            \{m,\}:至少m次

     位置锚定:用元字符要加引号
       ^:行首锚定:用于模式的最左侧;^root
       $:行尾锚定:用于模式的最右侧;
       ^PATTERN$:用PATTERN来匹配整行;PATTERN开头和结尾的行
          ^$:空白行;
          ^[[:space:]]*$:空行或包含空白字符的行;

       单词:非特殊字符组成的连续字符(字符串)都称为单词;
       \<或\b:词首锚定,用于单词模式的左侧;
       grep "\<root" /etc/fstab
       \>或\b:词尾锚定,用于单词模式的右侧;
       \<PATTERN\>:匹配完整单词;


  练习:
     1、显示/etc/passwd文件中不以/bin/bash结尾的行;
     2、找出/etc/passwd文件中两位数或三位数;
     3、找出/etc/rc.d/rc.sysinit或etc/grub2.cfg文件中,以至少一个空白字符开头,且后面非空白字符的行;
     4、找出"netstat-tan"命令的结果中以'LISTEN'后跟空白字符结尾的行;

   1、 grep  -v "\(/bin/bash\)$" /etc/passwd

   2、grep "\<[0-9]\{2,3\}\>"etc/passwd
   3、grep "^[[:space:]]\+[^[:space:]]" /etc/grub2.cfg
   4、netstat-tan |grep "LISTEN[[:space:]]*$"

重点: 分组及引用 ():将一个或多个字符捆绑在一起,当做一个整体进行处理; (xy)*ab 把xy当做一个整体

 注意:分组括号中的模式匹配到的内容会被正则表达式引擎自动记录于内部的变量中,这些变量为:
     \1:模式从左侧起,第一个左括号以及与之匹配的右括号之间的模式所匹配到的字符;
     \2:模式从左侧起,第二个左括号以及与之匹配的右括号之间的模式所匹配到的字符;
     \3:,,,


    he likes his lover
    he loves his lover
    he likes his liker
    he loves his liker

     grep "\(l..e\).*\1" lovers.txt

     后向引用:引用前面的分组括号中的模式所匹配到的字符;

正则表达式与grep

egrep: 支持扩展的正则表达式实现类似于grep文本过滤功能:grep -E

egrep [options] PATERN [FILE..] 选项: -i,-o,-v,-q,-A,-B,-C -G:支持基本正则表达式

 扩展正则表达式的元字符:
      字符匹配:
         .:任意单个字符
        []:指定范围内的任意单个字符
        [^]:指定范围外的任意单个字符

      次数匹配
     *:任意次,0,1或多次;
     ?:0次或1次,其前的字符可有可无的;
     +:其前字符至少1次;
     {m}:其前的字符m次;
     {m,n}至少m次,至多n次;
         {0,n}:最多n次
         {m}:最少m次

      位置锚定
       ^:行首锚定
       $:行尾锚定
       \<,\b:词首锚定
       \>,\b:词尾锚定

      分组及引用
        ():分组;括号内的模式匹配到字符会被记录于正则表达式引擎的内部变量中;
         后向引用:\1,\2...

       注意:只能在正则表达式中引用这些变量的值,不能在bash中引用

      或:
       a|b:a或者b;
           C|cat:C或cat
           (c|C):cat或Cat

 练习:
 1、找出/proc/meminfo文件中,所有以大写或小写s开头的行;至少有三种实现方式;         

 2、显示当前系统上root、centos或者user1用户的相关信息;
 3、找出/etc/rc.d/init.d/functions文件中某单词后面跟一个小括号的行;
 4、使用echo命令输出一绝对路径,使用egrep取出基名;取出其路径名
 5、找出ifconfig命令结果中的1-255之间的 数值;
 6、找出ifconfig命令
 7、添加用户bash,testbash,basher以及nologin(其shell为sbin/nologin);而后找出/etc/passwd文件中用户名同shell名的行;

1、grep -i "^s" /proc/meminfo grep "^[sS]" /proc/meminfo grep -E "^(s|S)" /proc/meminfo

2、grep -E "^(root|centos|user1)>" /etc/passwd 3、grep -E -o "[_[:alnum:]]+()" /etc/rc/d/init.d/ 4、 echo /etc/sysconfig/ |grep -E -o "[^/]+/?" 5、ifconfig | grep -E -o "\<([1-9]|[1-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])>" 6 7、grep -E "^([^:]+>).*\1$" /etc/passwd

fgrep:不支持正则表达式元字符: 当无需用到元字符去编写模式时,使用fgrep必能更好;

文本查看及处理工具:wc,cut,sort,uniq,diff,patch

wc:word count 单词统计
   wc [option]..[FILE]..
    -l:line
    -w:word
    -c:bytes

cut:从每一行中移除片段
   cut:option..[file]
      option:
          -d CHAR:以指定的字符为分隔符;
          -f FIELDS:挑选出的字段;
              #:指定的单个字段;
              #-#:连续的多个字段;
              #,#:离散的多个字段;

sort:
   sort [option]..[file]..
       -n:给予数值大小而非字符进行排序;
       -t CHAR:指定分隔符;
       -k#:用于排序比较的字段;
       -r:逆序排序;
       -f:忽略字符大小写;
       -u:重复的行只保留一份;
          重复行:连续且相同

 uniq:报告或移除重复的行
    -c:显示每行的重复次数;
    -u:仅显示未曾重复过的行;
    -d:仅显示重复过的行;

  diff:逐行比较文件中的内容
      diff [option]..FILES

      diff /PATH/TO/OLDFILE  /PATH/TO/NEWFILE > /PATH/TO/PATCH_FILE
        -u:使用unfied机制,即显示要修改的行的上下文,默认为3行;

  patch:向文件打不掉
     patch[options] -i /PATH/TO/PATCH_FILE /PATH/TO/OLDFILE

     patch /PATH/TO/OLDFILE < /PATH/TO/PATCH_FILE

原创文章,作者:15152188070,如若转载,请注明出处:http://www.178linux.com/30302