Linux_Shell脚本

发布时间 2023-08-09 17:04:53作者: Boldcc

Shell脚本


  • shell基础
  • shell变量
  • shell扩展

shell基础

shell简介

1.什么是shell?
	shell是一种命令解释器	
	shell也是一种编程语言
    	shell,python,perl三种

2.当前系统支持哪些shell?
    # cat /etc/shells 

3.如何改变当前shell?
    usermod,chsh
    
4.登录shell与非登录shell
    登录shell:以sh结尾的shell
    非登录shell: /sbin/nologin
    
5.父shell与子shell
     子shell能继承父shell的环境变量
     
6.环境是什么?
     命令,变量,资源...
    
7.如何配置环境?
      1)/etc/profile 
      2)/etc/bashrc   
      3)~/.bash_profile  //配置roo用户的环境变量
      4)~/.bashrc
      5)/home/tom/.bashrc   ///配置tom用户的环境变量
    所有用户登录都会加载这四个配置文件 
    /etc下两个为全局环境配置文件,对所有用户生效
    家目录下两个为用户自己的环境配置文件,只对用户本人生效

8.完全登录shell与非完全登录shell   
    完全登录会加载所有的环境配置文件   4个
    非完全登录只会加载部分文件             2个bashrc
    
9.linux命令的分类:
       内嵌命令     外部命令    别名      函数 
 -------------------------------------------------------------
 别名: alias
    查询别名: # alias
    设置别名: # alias  命令名称='动作'    
    取消别名: # unalias  别名名称      
--------------------------------------------------------------

10.历史命令
    history, 默认只记录1000条       
    清除历史命令: history -c

11.算术运算
        \+  -  *  /  %(取余,取模)   幂(**/^)
    1). echo $[] 或 echo $(())     只能计算整数   
    2). bc                                 可计算小数   ; 例: # echo 2.5+2.5 | bc  
    3). expr 10 + $num         运算符两边要有空格,通常用来判断参数是否整数
    4). let                                 通常作变量赋值
    
12.创建shell脚本
    • 第一行#!开头表示此程序由什么解释器来解释
    • #开头表示注释
    • 加上可执行权限
    
13.执行shell脚本
    1) 直接执行,在命令行写脚本的路径        开启子shell执行,将执行的结果返回到父shell中,前提,脚本要有可执行权限
    2) 调用解释器执行
    3) source 脚本的绝对路径,点执行  .  脚本的绝对路径     直接在当前shell下执行,会影响当前的shell环境

14.调试shell脚本
    sh -x  脚本路径

shell变量

变量

 用来存储信息的,其实是内存中的空间    
    变量的值是可以变化的

变量的命名规则:

  变量的名字一定是由字母. 数字和下划线组成,不能以数字开头,变量名不能使用关键字。变量名最好见名知意
shell中变量类型
shell中变量引用
shell中变量替换

变量类型:

    1.本地变量
    2.环境变量
    3.位置变量
    4.预定义变量

本地变量

  本地变量也叫自定义变量,用户根据自己的需求自己去定义的变量
    作用范围(作用域):在整个shell脚本中生效. 如果是在命令行定义的变量,作用范围是当前shell
    定义变量:变量名字=变量值   //注意:等号两边一定不能有空格

环境变量(全局变量)

作用范围:当前shell及其子shell
        env      查看所有环境变量
        set       查看所有变量
        export  定义环境变量
            1)将已有的本地变量导出成环境变量           
            2)在定义变量时,直接将其定义为环境变量
           注意:父shell会影响子shell,子shell不会影响父shell
           如果想让环境变量永久生效,就将其写在配置文件中

​    常用环境变量:
​        USER      /当前登录的用户
​        UID       /当前登录的用户uid
​        HOME      /当前登录的用户家目录
​        HOSTNAME  /当前的主机名 
​        PWD       /当前所在的目录
​        PS1       /
​        **PATH**          #系统查找外部命令的路径

位置变量

   $0 —— 表示当前运行的脚本或者命令本身
   $1~${10} —— 表示脚本的位置参数,$1就是第一个参数,依此类推   变量传参
   $# —— 表示参数个数
   $@和$* —— 表示参数的列表
   "$@" —— 将每一个参数看成独立的字符串打印,(纵向打印)
   "$*" —— 将所有参数看成一个字符串,(横向打印)

预定义变量

    $$ ——查看当前shell的pid   
    $? —— 上一条命令执行状态的返回值
        执行状态返回值(0-255),分两类
            0:正确执行
            1-255:错误执行                 

           
练习1:编写一个shell脚本,用于搜集其执行主机的信息,打印结果如下:
    # ./test.sh 
    2016年 11月 10日 星期四 17:07:45 CST
    当前的用户为 root
    当前用户的宿主目录为 /root
    用户的标识为 0
    主机名称为 guo.qfedu.com
练习2. 编写一个脚本给出系统的当前时间以及已经运行多长时间,并且列出所有登录系统的用户.最后脚本还会将这些信息写入一个日志文件/tmp/user.log
练习3.在练习1的基础上增加输出内容,要求打印如下:
    # ./test.sh 
    当前的日期为 2016/11/10 
    当前的用户为 root
    当前用户的宿主目录为 /root
    用户的标识为 0 
    主机名称为 guo.qfedu.com
    IP地址为 192.168.10.10
练习4:编写脚本实现一个计算器
    # ./calc.sh 5+4    echo $[$1]
    9


shell扩展 - read echo test 命令

read    echo   shift    sleep   basename  dirname   :  expect   test

read:功能就是读取键盘输入的值,并赋给变量

语法: read  [选项]  变量名
    选项:
    -p "  "   打印提示信息
    -n    限制输入字符数
    -t     限定输入时间,默认单位是秒
    -s    输入不显示
    -a    接受多个输入定义为数组

echo:最常用的输出命令,默认最后带一个换行符

   常用选项:
    -n    在同一行输出,即去掉了最后的换行符
    -e    支持\转义
            \n  换行符
            \t   制表符
            \r   光标回到行首  要与-n选项结合使用
            \b  删除前一个字符
            
    echo 也常用于打印空行或换行
    
    echo改变输出颜色:
        字体颜色      30-37     90-97
        echo -e "\033[字体颜色号m文本内容\033[0m"
        背景颜色    40-47
        echo -e "\033[背景颜色号;字体颜色号m文本内容\033[0m"

test 在脚本中用于判断真假

    语法:test   expression  或简写为[  expression  ]
        expression为test命令构造的表达式。这里expression是test命令可以理解的任何有效表达式.
    返回值:
        test命令或者返回0(真) 或者返回1(假).
    test可理解的表达式类型分为四类:
      1)判断表达式
        if  (表达式为真)
        if   ! 表达式为假
        表达式1 -a 表达式2    &&      两个表达式都为真
        表达式1 -o 表达式2    ||         两个表达式有一个为真
         
      2)判断字符串(一般用于判断变量)  加引号
        test –n  "字符串"            字符串的长度非零,则为真
        test –z  "字符串"            字符串的长度为零,则为真
        test "字符串1" == "字符串2"        字符串相等,则为真
        test "字符串1" != "字符串2"         字符串不等,则为真
         
      3)判断整数 
        test 整数1 -eq 整数2            整数相等
        test 整数1 -ge 整数2           整数1大于等于整数2
        test 整数1 -gt  整数 2            整数1大于整数2
        test 整数1 -le  整数 2            整数1小于等于整数2
        test 整数1 -lt   整数 2            整数1小于整数2
        test 整数1 -ne 整数 2           整数1不等于整数2
         
      4)判断文件 
        test File1 –ef File2              两个文件具有同样的设备号和i结点号
        test File1 –nt File2              文件1比文件2 新
        test File1 –ot File2              文件1比文件2 旧
        test –b File                 文件存在并且是块设备文件
        test –c File                 文件存在并且是字符设备文件
        test –d File                文件存在并且是目录
        test –e File                文件存在 exist
        test –f File                文件存在并且是普通文件
        test –g File                文件存在并且是设置了组ID
        test –G File                文件存在并且属于有效组ID
        test –h File                文件存在并且是一个符号链接(同-L)
        test –k File                    文件存在并且设置了sticky位
        test –b File                文件存在并且是块设备文件
        test –L File                 文件存在并且是一个符号链接(同-h)
        test –o File                 文件存在并且属于有效用户ID
        test –p File                  文件存在并且是一个命名管道
        test –r File                 文件存在并且可读
        test –s File                  文件存在并且是一个套接字
        test –t FD                  文件描述符是在一个终端打开的
        test –u File                文件存在并且设置了它的set-user-id位
        test –w File                 文件存在并且可写
        test –x File                 文件存在并且可执行
        
    注意:在使用[]简写test时,左中括号后面的空格和右括号前面的空格是必需的,如果没有空格,Shell不可能辨别表达式何时开始何时结束.

shell - 流控制

if
if判断的语法结构
    注意:if和fi要成对出现,脚本里有几个if就得有几个fi
    1)最简单的语法    
        if 条件表达式或者命令
        then
            命令;
        fi
       
     2)分支的if结构语法
         if 条件表达式或命令
         then
            命令;
         else
            命令;
         fi
         例子:判断文件/tmp/a.txt是否存在且为普通文件,若存在则提示文件已存在,否则创建文件a.txt并提示文件成功创建.

      3)多分支if结构语法结构
            if 条件表达式或者命令
            then
                命令;
            elif 条件表达式或命令    //elif可以有多个
                then
                   命令;
            else
                   命令;
             fi
 
练习
    1.提示用户输入想创建的用户名,判断若该用户名存在,则提示用户已存在,否则创建用户并提示用户成功创建.  
    2.改写练习1,先判断执行脚本的用户是不是root,如果是就执行练习1的操作;否则就提示不是root并退出。
    3.写一个脚本,从标准输入读取一个IP地址,如果用户输入的IP不为空就测试该主机是否存活,活着输出“alive”,否则输出“not alive”  ,如果为空,直接退出脚本

 
 多重条件判断
    条件表达式1 选项 条件表达式2
    选项:
        -a:并且      
        -o :或者
        ! 条件表达式 :取反,非
        if [ $username = "root"  -a  $password = "redhat" ]
        if [ $username = "root" ] && [ $password = "redhat" ]
        if [[ $username = "root" && $password = "redhat" ]]
case
case:多分支判断
语法结构:
    case 变量 in
      值1)
          命令;
          ;;
      值2)
          命令;
          ;;
       ... ...
          ;;
      值n)
          命令;
          ;;
       *)               //*表示匹配除了以上各个值之外的所有值
           命令;
            ;;
    esac


同时匹配两个变量的方法一:将两个变量看成一个整体
[root@srv254-200 scripts]# vim case2.sh
    #!/bin/bash
    read -p "Please input your name: " user_name
    read -s -p "Please input your password: " password
    case "$user_name $password" in
    "root redhat")
       echo "You are right."
       ;;
    "oracle ora")
       echo "You are right for oracle."
       ;;
    *)
       echo "You are wrong."
       ;;
    esac
[root@srv254-200 scripts]# sh case2.sh 
    Please input your name: root
    Please input your password: redhat
    You are right.
[root@srv254-200 scripts]# sh case2.sh 
    Please input your name: haha
    Please input your password: good
    You are wrong.
同时匹配两个变量的方法二:用逗号分隔多个变量    
[root@srv254-200 scripts]# vim case3.sh
    #!/bin/bash
    read -p "Please input your name: " user_name
    read -s -p "Please input your password: " password
    case $user_name,$password in
    root,redhat)
       echo "You are right."
       ;;
    oracle,ora)
       echo "You are right for oracle."
       ;;
    *)
       echo "You are wrong."
       ;;
    esac    
 
练习:
1.提示用户输入yes/no,读取用户输入,若输入是yes则提示输入的是yes,若输入是no则提示输入的是no,若输入的是其他,则提示只能输入yes或no
2.将1改写,用户输入yes或y都提示yes...
for
1. 语法结构
    for 变量 in 变量列表
    do
        循环体
    done
在命令行直接运行脚本命令   

变量列表决定循环次数。
    #for i in 1 2 3 4 5
    #for i in `seq 5`
    for i in {1..5}
    do
      echo $i
    done
练习:
    打印1-10之间的偶数


==================================================
插曲 —— seq
    # seq 1 2 10      //打印奇数        起始位置  步长  结束位置                                       
    # seq 5 10         //打印5到10      起始位置    结束位置    ,步长为1
    # seq -w 10       //等宽显示 :不够位数在前面补0
-------------------------------------------

练习:
    1. 用for循环,打印/etc/passwd的第一个字段
    2. 批量添加10个用户user01-user10,并设置密码,密码分别为pass01-pass10
    3. 用for循环在/haowan目录下批量创建10个文件,文件名为up-1,up-2,...,up-10
    4. 用for循环将第三题文件名中的up全部改成down
    5. 求1到100所有正整数之和
    6. 求1到100所有偶数之和
    7. 打印9*9乘法表
while
while语法:
    while 条件表达式或命令
    do
        循环体 //注意:循环体部分一定要有变量的更新,否则死循环
    done  
    
[root@srv254-200 scripts]# cat while.sh 
    #!/bin/bash
    i=1
    while [ $i -le 5 ]
    do
        echo $i
        let i++     //变量的更新
    done
    
 ------------------------------------
    i++:先用,后加1
    ++i:先加1,后用
 ------------------------------------

添加用户脚本,要求用户的信息来自于文本文件
[root@srv254-200 scripts]# cat user_list 
        tom:passtom:2014
        jack:passjack:2018
        mary:passmary:2016
        kite:passkite:2000
[root@srv254-200 scripts]# cat while1.sh 
    #!/bin/bash
    while read line
    do
      username=`echo $line | cut -d: -f1`
      password=`echo $line | cut -d: -f2`
      uid=`echo $line | cut -d: -f3`
      if id $username &> /dev/null
      then
        echo "exists"
      else
        useradd -u $uid $username && echo $password | passwd --stdin $username &> /dev/null
      fi
    done < /scripts/user_list      
      
   


练习:
    1. 使用while循环,添加user1-user10,分别设置密码为pass1-pass10,不添加user5  

    2. 使用while循环,将上题中的9个用户删除,删除成功给出如下提示“user xxx delete successfully.”

    3. 使用while循环计算1+2+3+...+100
    
    4.猜数字小游戏
    程序随机生成一个100以内的整数?
		echo $[$RANDOM%100+1]    (生成1-100的整数)
		(1、)要求游戏人员猜,最多只能猜6次?(6次机会)
		(2、)如果所猜的数字小于答案,程序要提示小了,反之提示大了?
		(3、)并且提示还剩下多少次机会?
		(4、)6次机会用完,提示正确答案?
		(5、)判断输入的数字是否是1-100之内
		(6、)判断输入的数字是否为纯数字
		疑问: 如果用户不输入,直接回车怎么办?
循环控制语法
continue:退出本次循环,直接进入下一次循环
break:退出整个循环,并不结束脚本,循环以下的内容还会继续执行
exit:退出脚本

数组

数组(array):
     把多个元素按一定顺序排列的集合,就是把有限个元素用一个名字命名,然后用编号区分他们的变量的集合,这个名字称为数组名,编号称为下标[index]。
     数组是可以保存一组值的变量
  
索引数组-----只支持整数下标
    1. 定义数组
        # nums=(2 5 8)           #下标从0开始,依次递增
        # nums[100]=hello
    2. 数组的调用 ${name[index]}
        # echo ${nums[1]}
            5
        # echo ${nums[*]}       #查看数组所有的值. * 整体    @ 个体
            2 5 8 hello
    3. 查看数组的下标
        # echo ${!nums[*]}       #按顺序列出所有值的下标
            0 1 2 100
    4. 数组的遍历
        1).遍历值
        2).遍历下标
    5. 数组的长度                         #元素的个数
        # echo ${#nums[@]}     
            4
    6. 取消数组
        # unset nums[100]          #取消数组中的一个元素
        # echo ${nums[@]}
            2 5 8
        # unset nums                    #取消整个数组

关联数组-----支持字符串下标
        # declare -A tom              #定义一个关联数组
        # tom[age]=20
        # tom[sex]=male
        # tom[addr]="guangzhou  tianhe"
        # echo ${tom[addr]}
            guangzhou
  
 练习: 编写双色球
 #!/bin/bash
reds=({1..33})
blues=({1..16})
blues_a=$[$RANDOM%16]
while [ ${#reds[@]} -gt 27 ]
do

        index=$[$RANDOM%33]

        if [ -z ${reds[$index]} ]
        then
                continue
        else
                echo -e "\033[31m${reds[$index]}\033[0m"
        fi
        unset reds[$index]

done | sort -n | tr -s "\n" " " 
echo -e "+ \033[34m${blues[$blues_a]}\033[0m"

函数

函数:function
    函数就是完成某个特定功能的一段脚本    
    函数不能独立运行,需要时通过函数名调用函数

一. 函数的定义
     function_name() {
     代码集
     }
 
二. 函数的调用
      直接使用函数名即可调用函数。
      如:function_name
      
练习:用函数写一个添加一个固定用户的脚本,然后在脚本中调用它
    #!/bin/bash
    USERADD() {
    USERNAME=test1
    if ! id $USERNAME &> /dev/null
    then
     useradd $USERNAME
     echo "user $USERNAME added"
    fi
   }
    USERADD    //调用函数

正则表达式

正则表达式(Regular Expression)
    正则表达式是一种字符特征的描述方式,用来在文本中匹配到用户想要的东西.

正则表达式与通配符:
    1.正则表达式一般用于处理文本内容,常用命令有grep,sed,awk,vim等
        通配符一般用于匹配文件名,常用命令有find,ls,cp等
    2.各符号的含义不尽相同.

什么地方使用正则表达式
    vim grep sed awk  nginx apache mail垃圾邮件过滤。。。  perl java python 等等都使用正则
    
构成
    1.元字符(基本元字符、扩展元字符)        
    2.除元字符之外的任意字符都是表示他字面意思的正则表达式
    
正则表达式的匹配过程 
    正则表达式是按照从表达式最左端第一个字符开始,左到右依次一个一个字符进行匹配.当字符串中有字符成功匹配到正则表达式中字符,则从这个位置开始尝试正则表达式中的下一个字符进行匹配,如果匹配成功则继续从这个位置开始匹配正则表达式中下一个字符;如果匹配不成功,则“回溯”到第一次匹配的字符处重新从正则表达式中第一个字符开始匹配。
        
        
特征
    贪婪匹配

基本元字符 
    字符匹配
        .       任意单个字符
        []      []内的任意单个字符
                [^]  首位为^表示取反
                [a-z]  小写字母
                [0-9]   数字
                [A-Z] 大写字母
                [a-zA-Z] 所有字母
                [^a-zA-Z0-9] 所有符号
        
    次数匹配
        *               匹配*前面的字符重复0次到多次
        \{n\}        匹配前面的字符刚好重复n次
                        \{n,m\}    前面的字符重复n次到m次 
                        \{,n\}       前面的字符最多重复n次
                        \{n,\}       前面的字符最少重复n次
    位置匹配
        ^           行首
        $           行尾
        \<          词首
        \>          词尾
        
扩展元字符 Extended Metacharacters (egrep and awk)
        +           前面的字符至少重复1次
        ?           前面的字符重复0次或1次
        |             或
        {}          次数匹配
        ()          分组
        \数字    引用分组的内容      1-9
                     前向: 在正则中引用
                     后向: 在其他地方引用, \0表示引用模式中所有的内容   \0 ⇔ &
                     
                     
编写正则表达式的3 个步骤:
    1 知道要匹配的内容以及它如何出现在文本中。
    2 编写一个模式来描述要匹配的内容
    3 测试模式来查看它匹配的内容,不能错,不能漏,不能多

练习:head /etc/passwd > /tmp/pass
    1. 删除每行的第一个字符
    sed '/.//' /tmp/pass
    2. 在每行行首插入hello
    sed  's/^/hello/' /tmp/pass
    3. 删除每行的第二个字符
    sed -r 's/(.)(.)/\1/'  /tmp/pass
    4. 把每个数字用()括起来   如:(1)(2)
    sed -r 's/([0-9])/(\1)/'  /tmp/pass
    5. 把每个数值用()括起来   如:(12)
     sed -r 's/[0-9]+/(\0)/g'  /tmp/pass
    6. 删除每行的倒数第二个字符
    sed -r 's/(.)(.)$/\2/' /tmp/pass
    7. 交换每行的第一个和最后一个字符
     sed -r 's/(.)(.*)(.)/\3\2\1/g' /tmp/pass
    8. 删除刚好三个字符的单词
    sed -r 's/\<[a-zA-Z]{3}\>//g' /tmp/pass
    9. 把ro或da替换成A
    sed -r 's/ro|da/A/g' /tmp/pass
思考:
    1. 删除每行的第一个单词(纯字母)
     sed -r  's/[a-zA-Z]+//'  /tmp/pass
    2. 交换第一个和倒数第二个单词(纯字母)
    sed -r 's/([a-zA-Z]+)(.*)([^a-zA-Z]+)([a-zA-Z]+)([^a-zA-Z]+)([a-zA-Z]+)/\4\2\3\1\5\6/'  /tmp/pass

sed

文本的操作
sed是一个“非交互式的”面向字符流的编辑器。
awk是一种负责模式匹配的程序设计语言,,的典型示例是将数据转换成格式化的报表。

sed  stream editor
    是一种文本编辑器,默认情况下是不会修改原文件的。
    也是一种非交互式的编辑器
    
 
工作原理
    一行一行处理的
    当从文件中读取一行后,首先放到模式空间中对该行进行相应的处理,处理完将结果输出到屏幕上。然后继续读取下一行内容,直到所有行都读取完毕,sed结束。
    
       
  语法:
    sed    [选项]   '模式动作'  文件...
    
  选项:
        -n:静默输出,关闭模式空间的输出,不会输出未匹配到的行 一般与p命令结合使用
        -e:允许进行多项编辑,也就是说对同一行做多次处理、. 可以做多点编辑  
                -e '动作1'  -e '动作2'   ==  '动作1;动作2'
        -f: 后接sed脚本,指定执行的sed脚本(将模式动作写到文件中)
        -r:允许使用扩展正则
        -i:直接作用于原文件    没有输出  在使用-i之前一定先不加-i看看效果
            -i.bak:修改原文件之前进行备份
                
  模式:
    1. 空模式,表示所有的行都执行动作
    2. 以行号作为模式
        1). 单独的行号
             如:1   就是处理第1行
                 $   处理最后一行
        2). 起始行,结束行
              如:1,5     处理第1到5行
        3). 起始行~步长
              每隔多少行操作一次
              如:2~2 处理第2行开始,+2 行进行处理
              	 2~3 处理第2行开始,+3 行进行处理
        4). 起始位置,+N
             表示从起始位置开始,后面的N行都进行处理
             如:3,+5   处理3-8行
    3. 以正则作为模式             
        1). /正则表达式/
            如:/^root/
        2). /正则表达式1/,/正则表达式2/
           表示从第一次匹配到正则表达式1开始到第一次匹配到正则表达式2之间的所有行
              如:/^bin/,/sh$/
        
  动作-----处理命令:   ! 非 : 放在命令前面表示取反
    1. d    删除       delete               
    2. p    打印       print
    3. r     读取       read              
    4. w    写          write
    5. a     追加   在匹配的行下面插入内容            append   
    6. i      插入   在匹配行的上一行插入内容         insert
    7. c     修改    本行替换                                   change
    8. y     转换的命令,一一对应转换
    9. n     处理下一行                                          next
    10. q    退出,不会再向模式空间读入新的行       quit
    11. s    查找替换
        '模式s/旧的内容(正则表达式)/替换内容(新的内容)/[修饰符]'
            修饰符:
                g:全局替换
                n:n为数字,1-512    替换第n个匹配到的内容
                p:打印      -n
                w:把处理过的行写入到另一个文件
 
练习:
    1.以root开头的行,到以bash结尾的行,将bin替换为sbin (/etc/passwd文件或其一部分)
     sed "/^root/,/bash$/ s/bin/sbin/g" pass
    2. 将格式为2014/08/17的日期,替换为2014; 08; 17这样的格式(注意:分号后面有空格) 
     date +%Y/%m/%d | sed "s/\//; /g" 
    3. 将pass文件每行打印3次
     sed "p;p" pass
    4. 打印pass文件的第1行和第3行
    sed "1p;3p" pass
    5. 删除pass文件的第一行和最后一行
     sed -n "1p;3p" pass
    6. 删除pass文件中所有的数字
    sed -r "s/[0-9]//g" pass
    7. 将文件中所有的root单词(仅root,不操作rooter这样的单词)替换为ROOT
    sed -r "s/\<root\>/ROOT/g" pass
    8. 在文件的第一行插入information
    sed "1i information" pass
    9. 将含有root的行的内容替换为ROOT
    sed -r "/root/ s/.*/ROOT/g" pass
    sed "/root/ c ROOT" pass
	
    10. 将文件中所有的abc替换为大写字母
    sed -r "s/[abc]/\u&/g" pass
    11. 用sed分别实现head -1和tail -1的功能
    sed -n "1p" pass
    sed -n '$p' pass  
 

-----------------------------------------------------------------------    
    \u   upper   大写字母
    \l    lower    小写字母
    
    将文件中所有小写字母替换成大写字母:
    # sed  's/[a-z]/\u&/g'  /tmp/pass

awk

awk   文本编辑器. 也是一种非交互式的编辑器
         一种编程语言

功能:
    对文本数据进行汇总和处理,是一个报告生成器,能够对数据进行排版
         
工作模式
    1. 行工作模式,读入一行文件,存在“$0”里                      
    2. 使用内置变量FS(字段分隔符)分割一行,存到$1-$100     
    3. 输出时也是用内置变量OFS,输出该行
    
与sed主要异同:
相同点:
    1.他们的语法基本相同
    2.他们都是流编辑器,工作方式都是读入一行,处理动作,输出结果
    3.他们都可以使用正则表达式作模式匹配
    4.他们都允许使用脚本
不同点:
    1.sed主要处理行,awk主要处理列
    2.sed处理动作必须与文件内容相关,awk处理动作可以与文件内容无关,并且awk的动作要用{}括起来.
 
1. awk的语法
    awk   [选项]   '模式{动作...}'   文件列表...
    选项:
    	-F   //以什么为分隔符,默认是以空格为分隔符
    模式:
    	/^root    //以root开头的行
    	NR==2     //第二行,   NR 代表行的意思
    	NR>3	  //匹配前两行
    动作:
    	print	  //打印
    		$1		//第一列  
    		$NF		//最后一列   NF代表列
    【会取值】		
2、案例
	1)、打印/etc/passwd 文件的用户名 UID  GID 以及登入shell 
	# awk -F":" '{print $1,$3,$4,$7}' /etc/passwd           //默认以一个空格隔开
	2)、执行ifconfig ens33 , 直接获取IP地址
	# ifconfig ens33 | awk -F" " 'NR==2{print $2}'