[RedHat笔记]第三课:变量的种类及用法,alias命令,环境变量的分类和修改,输入输出重定向,for循环,文本处理类命令,grep命令,短路操作(&& ||)

----------------------------------------

回顾系统变量:   

 变量有4种类型:

     1.本地变量。对子shell是无效的
     2.环境变量。 不但对当前shell有效,还对子shell有效的。

            声明的时候一定要用 export 来声明,表示导出一个变量

           export A=3 (直接导出)
            或者
            A=3
            export A

          Bash为用户准备了许多变量,以支持用户来调用

          系统中到底有哪些环境变量呢?
          
          export 不带任何选项的此命令,就能看出现在正在被使用的环境变量。
            DISPLAY="" 用于定义你当前桌面在哪个位置显示,哪个屏幕显示
             HISTSIZE=""命令历史当中可以保存过去多少条命令的 (需要记住的)
            HOME= 用于表示当前用户的家目录的
            HOSTNAME= 用于表示主机名
            LANG= 主机语言
            LOGNAME= 登录到当前用户的用户是
            PATH= 外部命令查找的可执行文件的访问路径
            PWD= 显示当前目录
            OLDPWD= 其实就是 cd - 在上一个目录之间前换
            SHELL= 当前shell
            USER= 当前用户
            PS1= 显示头部文件
                     当前环境变量的某些值来替换 \u 用户名 \h主机名 \W 基名 \$ 管理员用# 其他用户用$
                     \! 命令在历史行里是第多少条命令
                     \t 显示时间
                   恢复成原本
                   export PS1='[\u@\h \W]\$' (这是原有方式
                   特殊标识方法
                   '[\033[31m\u\033[0m@\h \W]\]$' 加颜色
                   \033其实是一种ASII码,控制颜色的
                    
          printenv 显示部分环境变量
          env 表示你可以在一个指定的环境下运行某个命令
     3.特殊变量。
          也是Bash内置的变量,
              最著名的变量:$?  
              用于表示上一个命令的执行结果,用于看上一个命令是否执行成功了。
              在linux编程中,0 永远表示 上一个命令成功了,如果失败了,会用1-255表示。
              一般来讲,只要是大于0,都是没有执行成功的。但每个错误会有不同的错误返回值。
     4.位置变量。用这个变量本身的位置调用的
          比如$1 $2 $3... . 可以直接向脚本调用参数并应用的
          脚本中
          echo "the first param: $1"
          echo "the 2 param $2"
          echo "the 3 param $3"


          在命令行下 1sh.sh a b c 则直接将a b c 变为 $1 $2 $3
          --------------------------
          扩展:算术运算
          A=2
          A=3
          echo "$[$A+$B]"  则显示结果
          echo "$(($A+$B))" 用$加双括号,也可以显示
          --------------------------
         练习:想命令行传递两个任意整数并算出两个整数的和:
             #!/bin/bash             
             echo "The sum is : $[$1+$2]"
             保存,命令行
             ./sum.sh 4 5 : 则内部将4直接赋值给$1 ,5赋值给$2 并显示运算结果


          --------------------------
       
BASH的命令别名:
      我们可以给命令取上别名。
      alias命令:
      alias cls=clear 则可以将clear加一个别名为cls
      alias cdnet='cd /etc/sysconfig/network-scripts' 则将CD这条命令简写成一个词

      不想用alias的话
       unalias 命令
      比如
      unalias cdnet.

     *******环境变量,BASH别名什么的,只对当前变量生效,重启之后都没有了。通过命令的方式,仅仅是临时保存。
     *******但是PS1等变量还是有效。因为我们把自己的文件保存到了系统的变量中,它将直接保存。                    
    
      如果想让他们重启还生效。则需要修改相关的文件
      刚刚装完系统之后,为了初始化所有用户的初始环境,系统有一个全局设置
      而用户还有自有的特殊的,局部有效的配置文件。
      全局的表示对所有用户有效
      局部的表示对特有用户有效
      当既有全局又有局部的时候,则局部生效
       全局有效的配置文件
        /etc/profile , 
        /etc/profile.d/*  , 
        /etc/bashrc
      
       局部有效的配置文件们
      ~/.bash_profile
      ~/.bashre,
      ~/.bash_.logout
      
      这些文件分两类,
       1是profile类
        通常是用来设置环境变量的。
        用来运行一些命令的(用户登录时要执行的命令)
       2是bashrc类
        一般来讲是用来设置别名的
        用于设置本地变量
        
 shell对用户来讲,分为两大类。
  1 交互式登录式shell ,以一个用户的身份输入账号和密码之后直接输入命令的shell
      运行次序:/etc/profile --> /etc/profile.d/* --> ~/.bash_profile --> ~/.bashrc --> /etc/bashrc
  2.非登录式shell  :当运行一个脚本时系统自动运行的shell
      运行次序:~/.bashrc --> /etc/bashrc --> /etc/profile.d/*
  ------------------------
     PATH命令:声明在profile里。
           很有可能需要手动进去声明它的脚本变量。
 -------------------------
     比如声明: alias cdnet 使之全局有效
     nano /etc/bashrc   编辑 bashrc 文件
     alias cdnet='cd /etc/sysconfig/network-scripts'

     如果只想让一个用户有效则:进入用户家目录: ~/.bashrc里加入
 ----------------------------------
     如何去声明一个环境变量:
        比如定义环境变量
           FAVORCOLOR=blue  使之对所有用户都有效
        可以在/etc/profile里声明也可以在 /etc/profile.d/*里声明
        etc/profile.d其实是为了减少  etc/profile的文件体积,并且让其管理起来方便
 
        进入profile 最后
        export FAVORCOLOR='Blue'
 ----------------------------------
 
    任何用户是在读取这个变量的时候是在登录的那一刻读取的。
    已经登录的用户并不受影响
-----------------------------------
   如何使修改的登录变量立即有效?
      使用source 命令,重读一下配置文件
       source /etc/profile
      使用“.” 命令,重读一下配置文件
      其实 . = source 
      比如 . /etc/profile
             不建议使用source ,会影响到其他变量的使用。
 
 --------------------------------
 小思考:想让用户登录进来时能够显示一句话:
             Hi,I know you ,you are root.
             让用户登录的时候加入一句:请注意个人言行
  练习:写一个脚本,
           传递两个整数给脚本,让脚本分别计算并显示这两个整数的和差积商
           Bash不能做浮点运算
           
         为了避免展开
         echo '$5000' 可以在强引用里使用
         也可以
         echo "\$5000" 反斜杠,永远是为了避免展开的,避免转义的。
         echo \" \" 则能将 “” 显示出来
         
 ----------------------------------
   Shell的输入输出重定向功能,管道
          默认情况下,当你执行完一个命令,这个命令必然会输出一些信息,但是这个信息输出到了什么位置呢?
          输入设备和输出设备有很多种,大多时候,进行命令时,可能都没有明确说明应该输出到什么地方去,或者从什么输入
          当你不指定的时候,linux会输入输出到默认设备上去。
      -------------------    
      标准输入:0, 一般指键盘 keyboard  
            /dev/stdin  (标准输入设备,显示为浅绿色),
                              其实是一种链接文件。用ll可以看出它有指向。
                              大多数情况下,我们用0 来表示:文件描述符
             重定向一般用 < 表示
                   比如 
                         cat < /etc/fstab 则将fstab的内容输入到了cat下,并用cat命令显示
      --------------------                   
      标准输出: 1,默认是显示器 monitor
            /dev/stdout  
             重定向一般用 1> 表示
                  比如
                       ls > /tmp/ls.out 则将ls的内容,输出到了 /tmp/ls.out
       --------------------     
      错误输出: 2,默认是显示器 monitor
            /dev/stderr     
             重定向一般用 2> 表示
                  比如:
                        lss 2> /tmp/ls2.out
                  但是当你这个信息是正确时候,它不会输出到指定,而是直接显示
       ---------------------           
       合并标准输出和错误输出的输出流:
       " &> " 使用它可以合并。
       ---------------------
       输出重定向会覆盖文件的原有内容,所以,
       " > "号叫覆盖输出重定向 
       " >> "号叫追加输出重定向,可以追加内容,而不覆盖

       
       很多时候,我们可以使用echo命令,往一个文件的最后一行追加一行文字
       echo "-------------------" >> /tmp/ls.out
       
       ---------------------
       
       当使用“2>>” 时可以追加错误重定向
       但 "&>>"是不支持双大于号来追加所有内容的。
       ---------------------
       有时会出现手误少打一个>导致,直接覆盖了原有内容而导致不得恢复
               set -C 命令,打开了禁止使用覆盖重定向 ,想开启的话
              set +C 命令。关闭禁止使用覆盖重定向

       有时我们就是想覆盖文件的话。
              ">| "符号后面加一个竖线,则表示我清楚我在做什么,我非要覆盖。
       ---------------------    
       如何实现将正确的输出流保存在1.txt ,如果错误,则保存错误到2.txt呢?
             ls /var >> /tmp/1.txt 2>> /tmp/2.txt 
             意思是将 ls /var的输出结果 正确的话追加到1.txt ,错误的话追加到 2.txt 只不过这两个符号要分开使用,中间加空格。
                
 ----------------------------------------------------
     管道:" | "
          COMMAND1 | COMMAND2 | COMMAND3....
                   
          管道的作用:把前一个命令的输入输出执行结果,当做第二个命令的输入命令来处理。

比如:

       ls -l /etc | less
              则是将 ls -l /etc 的输出结果,在less中输入,则可以使用less 查看

              比如:
             echo "123456" | passwd redhat
              将123456的结果通过管道输送给 用户redhat的passwd中。 
         
          可以连接多个命令,不光是两个命令的链接。比如:
              ls -l /etc | sort -t | less
               反向排序之后送给less查看 
              
          既想送给less命令分页查看,又想保存一份到文件里去
              ls -l /etc | tee /tmp/ls.out | less
              tee:会把数据流分成两部分,一部分保存,一部分送给后面的命令
              则,将数据先保存一份到ls.out,再用less命令查看
          
          有多个命令的输出,都需要保存在同一文件。为了实现:
              command >> a.out
              command2 >> a.out
              则可以使用一个变量,用脚本实现。但是麻烦,所以

  

  自定义输出重定向:可以用(3-9)的数字

               exec : 
              exec 3> /tmp/myout.out  (也可以用追加">>" 或者读入"<" )
              则将3定向为了 myout.out 其实是覆盖为了这个文件
              之后
              ls /var >&3  (必须用 >& 符号)
              则会将显示结果覆盖至 自定义的一个输出重定向 3中
           在多次重定向的场景里,避免多次的反复重定向的那个文件而导致的频繁打开和关闭。
           撤销:
              exec 3>&-
              这样就关闭了此文件
              
     /dev/null:数据黑洞,设备文件的空文件。会把所有送来的数据吞噬掉。
                      我们可以实现把那些输出出来没用的数据,送到这里
                      这样不会占用任何空间。(属于虚拟设备)

====================================
  程序执行流:
  顺序执行:一般来说,程序执行的次序都是顺序执行的。(执行流的一种)
  选择分支:选择一种特定的,条件满足时则执行的分支
  循环执行:当你满足特定条件时,会反复的执行一遍又一遍直到条件不满足
  
  ===================================
   循环执行:for
        想在系统上加入10个用户,user1,user2.....user10。
        在脚本编程中,使用
        格式:
         for I in LIST; do
             statement1
             statement2
        done

        
        第一次,它将I的值取为1,LIST1 之后执行一遍
        之后将I的值取为 LIST2....
        
        for I in 1 2 3 4 5 6 7 8 9 10; do
             useradd user$I
             echo user$I | passwd --stdin user$I
        done

        则,会自动添加user1-10并将其密码设置为自己的用户名。
        --------为了方便--------
        1.  seq 1 10 : 表示,以1开始以10结束的数字展开为一个序列,但是使用的时候要用命令替换
        比如
           for I in `seq 1 10`; do
         2.  {1..10} :也表示取整数序列,从哪开始,从哪结束。
        -------------------------
        
  ------------------------------------------------------
  扩展练习:
     ping 192.168.0.151--192.168.0.254的,每个ping 一次
         ping 一次的方式: -c 1 
     
写一个脚本:
1、切换工作目录至/var
2、依次向/var目录中的每个文件或子目录问好,形如:
(提示:for FILE in /var/*; 或for FILE in `ls /var`; )
   Hello, log
   Hello, run
3、统计/var目录下共有多个文件,并显示出来


         解答:
         #!/bin/bash
         #
         cd /var
         for FILE in /var/*; do                   
         echo "Hello, $FILE "
         done
         echo "There is `ls -l | wc -l` files."

         -----------------------------
         也可以最开始赋值SUM
         let SUM=0
         在循环里,
         SUM=$[$SUM+1]
         最后显示SUM就好。


写一个脚本:
1、设定变量FILE的值为/etc/passwd
2、使用循环读取文件/etc/passwd的第2,4,6,10,13,15行,并显示其内容;
(提示:LINE=`head -2 /etc/passwd | tail -1`可以取得第2行)
3、把这些行保存至/tmp/mypasswd文件中
         
        #!/bin/bash
        #
        FILE=/etc/passwd

        for I in 2 4 6 10 13 15; do
        echo "LINE$I=`head -"$I" $FILE | tail -1`"
        echo LINE$I=`head -"$I" $FILE | tail -1` >> /tmp/mypasswd
        done

       ------------------------------
        方法二
        FILE='/etc/passwd'
        exec 3>> /tmp/mypasswd   #####自定义追加输出重定向
        for I in 2 4 6 10 13 15; do
          LINE=`head -$I $FILE | tail -1`
          echo $LINE
          echo $LINE >&3
        done
        exec 3>&-           #####撤销输出重定向
        unset FILE LINE    #####撤销变量
      
 =============下=====午================
    文本处理类命令:
   cut
: 将文本内容一行一行的按照某种格式给他剪裂开来
        -d :用于指定分隔符。“d:”以“:”分割
        -f : 用于指定取第几段 -f1 则为第一段
        比如
        tail -1 /etc/passwd | cut -d: -f6,7
         则以:为分割,取第6段和第7段 
        
        LINES=`wc -l /etc/passwd | cut -d" " f1`
        echo $LINES
        行数统计,统计完成之后,对每一行进行切割,再向用户进行问好
            
  =============================\
 练习:
  1, 设定变量FILE的值为/etc/passwd
  2,向/etc/passwd 下的 用户问好,
  3,统计一共有多少用户
  #!/bin/bash
  
  FILE='/etc/passwd'
  LINES=`wc -l $FILE | cut -d" " -f1`
  for I in `seq 1 $LINES`; do
      USERNAME=`head -$I $FILE | tail -l | cut -d: -f1`
      USERID=`head -$I $FILE | tail -l | cut -d: -f3`
      echo "Hello, $USERNAME, Your UID is $USERID"
   done
   echo "$LINES users."
   unset LINES FILE USERNAME USERID
       
   练习2:
  1, 设定变量FILE的值为/etc/passwd
  2,向/etc/passwd 下的 用户问好,并说出对方ID是什么,形如:
  Hello,root,your UID is 0
  3,统计一共有多少用户
 
#!/bin/bash
#
FILE='/etc/passwd'
LINES=`wc -l $FILE | cut -d" " -f1`
for I in `seq 1 $LINES`; do
  USERNAME=`head -$I $FILE | tail -1 | cut -d: -f1`
  USERID=`head -$I $FILE | tail -1 | cut -d: -f3`
  echo "Hello, $USERNAME,Your UID is $USERID"
done
echo "$LINES users."
unset LINES FILE USERNAME USERID
  
 ===================================
总结 for循环:
   for VAR in LIST; do
       statement;
       statement;
       ...
    done

   
    LIST的表述形式:
    简单列表:1 2 3 4
    复杂列表: This is Tom\'s cat (此时里面的小分号不被LIST识别,需要转义符)
    变量  `seq 1 $LINES`
    命令  `ls /var`
    通配符 for I in /var/*
    
-------------------------------
为了一次能从/etc/passwd下取一行,简单的可以使用:
  for LINE in `cat /etc/passwd`; do  
  但是空格,TAB,换行符都被LIST识别为拆分
  为了避免空格被拆分成一个独立的值去计算,需要在拆分前告诉LIST,
  只需要修改$IFS的值为只识别换行值:
        IFS=$'\n'
        

       所以将刚才的练习2,重新可以编译成:
       #!/bin/bash
       #
       IFS=$'\n'          ##### 只识别换行符为拆分
       let SUM=0           ##### 将SUM从数值型升为整形
       for LINE in `cat /etc/passwd`; do     ####将cat显示的结果依次输出循环
         USERNAME=`echo $LINE | cut -d: -f1`     ####取
         USERID=`echo $LINE |cut -d: -f3`
         echo "Hello, $USERNAME,your ID is $USERID."
         SUM=$[$SUM+1]
       done
       echo "$SUM users."
 --------------------------      
SUM是数值型的,为了让他升值为整形,需要
let SUM=0
============================


grep 命令: 全面搜索正则表达式并显示出来,它是一个家族,家族中分别有
     1.grep   
     2.egrep
     3.fgrep
     正则表达式(re):其实就是元字符,用一堆的元字符组成,按照一定的规则组成起来,能够实现过滤匹配不同的文本内容。

           1.基本正则表达式
           2.扩展正则表达式,比基本略多
    ----------- 
     格式
     grep [options] "PATTERN" file   

      能够根据你所指的模式(PATTERN),从文件中将他找到并显示出来

      比如:
        grep 'root' /etc/passwd
        搜索/etc/passwd中的含有root的信息
        
        常用选项
            -i : 不在乎字符的大小写
            -v:跟默认的动作正好相反(取反),只显示那些没有匹配的
            -n:能够显示所匹配的行在文中所处得行号(行号显示)
            -An:显示结果,并显示结果之后的n行
            -Bn:显示结果,并显示结果之前的n行
            -Cn:显示结果,并显示结果的前 和 后 n 行
            
            --color:会把匹配这个模式的字符串高亮显示
         
         常用模式 :正则表达式种类
            ^   定义行首,行首匹配锚定符
            $    定义行尾,行尾匹配锚定符
            .     匹配任意单个字符,相当于"?"
            *    次数匹配,表示匹配符前面的这个字符所出现的0次或者任意次。
            ?    次数匹配,表示匹配符前面的这个字符所出现的0次或者1次。
            [  ]  匹配一组字符中的任意一个字符
            [x-y]  匹配指定范围内的一个字符
            [^ ]   表示否定
            \<  词首定位符,必须是单词,而不能是字符
            \>  词尾定位符
            \<..\> 精确匹配
            \(..\)  撇配稍后将要使用的字符的标签
            x\{m\}  表示x精确出现m次
            x\{m,\}  表示x至少出现m次
            x\{m,n\} 表示x至少出现m次,且不超过n次
            grep --color "root{1}quot; grep.txt   表示root必须出现在行尾
            grep --color "\<root\>" grep.txt  表示要精确匹配root这个单词
            grep --color "root\{1,\}" grep.txt 至少匹配1次
            grep --color "root\{1\}" grep.txt 表示精确匹配1次
            grep --color "root\{0,1\}" grep.txt 表示至多出现 1次
            grep --color "\(root\).*\1able" grep.txt 
            包含了root中间跟了任意字符,后又跟了\1又出现了引用最前面的字符的以及 able字符的字符

            
    
===练习============
练习:
1、显示/proc/meminfo文件中以不区分大小的s开头的行;
2、显示/etc/passwd中以nologin结尾的行;
3、显示/etc/inittab中以#开头,且后面跟一个或多个空白字符,而后又跟了任意字符的行;
4、显示/etc/inittab中包含了:一个数字:(即两个冒号中间一个数字)的行;
5、显示/boot/grub/grub.conf文件中以一个或多个空白字符开头的行;
6、显示/etc/inittab文件中以一个数字开头并以一个与开头数字相同的数字结尾的行;
7、ifconfig命令可以显示当前主机的IP地址相关的信息等,如果使用grep等文本处理命令取出本机的各IP地址,要求不包括127.0.0.1;
8、显示/etc/sysconfig/network-scripts/ifcfg-eth0文件中的包含了类似IP地址点分十进制数字格式的行;

   1  grep -i --color "^s" /proc/meminfo
   2  grep --color "nologin{1}quot; /etc/passwd
   3  grep --color "^#[[:space:]]\{1,\}.*" /etc/inittab
   4  grep --color ":[0-9]:" /etc/inittab
   5  grep --color "^[[:space:]]\{1,\}.*" /boot/grub/grub.conf
   6  grep --color "\([0-9]\).*\1{1}quot; /etc/inittab
   7  ifconfig | grep "inet addr" | grep -v '127.0.0.1' | cut -d: -f2 | cut -d" " -f1
   8  grep "[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}" /etc/sysconfig/network-scripts/ifcfg-eth0 
   =================== 
   egrep,grep -E
      与grep基本相同,但是没有了 \()之类的字符
        {n} : 精确匹配前面的 n次
        + :匹配一个或多个+号前的字符,相当于 \{1,\}
        ?   : 相当于\{0,1\},匹配此前的字符,1次或0次
        a|b : 匹配a或b
        ( ) : 字符组,把括号里的当做一个单位 
    ====================

    练习,用egrep实现上面的练习。

    1. egrep -i --color "^s" /proc/meminfo
    2. egrep --color "nologin{1}quot; /etc/passwd
    3. egrep --color "^#[[:space:]]+.*" /etc/inittab
    4. egrep --color ":[0-9]:" /etc/inittab 
    5. egrep --color "^[[:space:]]+.*" /boot/grub/grub.conf
    6.
    7. ifconfig | egrep "inet addr" | egrep -v '127.0.0.1' | cut -d: -f2 | cut -d" " -f1
    8. egrep "([0-9]{1,3}\.){3}[0-9]{1,3}" /etc/sysconfig/network-scripts/ifcfg-eth0

   =====================
   
  变量 $?  : 表示上一个命令的执行结果 ,表示执行成功了还是失败了。
  结果显示:
  0 : 成功了
  1-255 : 都表示失败了        
  事实上我们可以实现以逻辑连接命令来来连接两个命令

=======================  

与操作

   command && command: 这表示 只有前面的命令成功了,才执行后面的命令     
      1 && 0 = 0 意思是前面的命令即使执行成功了,也需要执行后面的命令,才能判断是否成功
              即: 短路操作、
              只要前面为0,结果肯定为0
  
  或操作
   command || command  : 如果前面不成功,则执行后面的 
      短路操作:
      1 || ? = 1 :前面已经成功的时候,后面就不执行了,直接判定成功
        只要前面为1,后面肯定为1 
      0 ||  ? = ?
        若前面不成功,则必须执行后面的命令才行
   
   grep "root" /etc/passwd || useradd root
   判断是否需要执行这个用户,如果前面否定,则执行后面,意思是,若没有用户,则创建。  
   ==================
   练习: 
   写一个脚本:
   1.添加10个用户,user1 --- user 10 ,但要求只有用户不存在的情况下才能添加

                   解答:

   #!/bin/bash
   #
   for I in {1..10}; do
     grep "user$I" /etc/passwd || useradd user$I
   done


   写一个脚本
   1.通过 ping命令测试,192.168.0.151到192.168.0.254之间的所有主机是否在线
   如果在线,则显示“ip is up” (ip 要换成真正的ip)
   如果不在线,则显示“ip is down”   
   提示:ping -c1 -W1 192.168.0.254 &> /dev/null && echo "192.168.0.254 is up." || echo "192.168.0.254 is down."
   ping 

      -Wn :如果超时,则过n秒后自动跳过

      解答:

      #!/bin/bash
      #
      for I in {151..254}; do
        ping -c1 -W1 192.168.0.$I &> /dev/null && echo "192.168.0.$I is up." || echo "192.168.0.$I is down."
      done


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值