`
天梯梦
  • 浏览: 13625057 次
  • 性别: Icon_minigender_2
  • 来自: 洛杉矶
社区版块
存档分类
最新评论

Linux Shell高级技巧(三)

 
阅读更多

十三、格式化输出指定用户的当前运行进程:

      在这个例子中,我们通过脚本参数的形式,将用户列表传递给该脚本,脚本在读取参数后,以树的形式将用户列表中用户的所属进程打印出来。
      /> cat > test13.sh
      #!/bin/sh
      #1. 循环读取脚本参数,构造egrep可以识别的用户列表变量(基于grep的扩展正则表达式)。
      #2. userlist变量尚未赋值,则直接使用第一个参数为它赋值。
      #3. 如果已经赋值,且脚本参数中存在多个用户,这里需要在每个用户名之间加一个竖线,在egrep中,竖线是分割的元素之间是或的关系。
      #4. shift命令向左移动一个脚本的位置参数,这样可以使循环中始终操作第一个参数。
      while [ $# -gt 0 ]

      do
          if [ -z "$userlist" ]; then
              userlist="$1"
          else
              userlist="$userlist|$1"
          fi
           shift
      done
      #5. 如果没有用户列表,则搜索所有用户的进程。
      #6. "^ *($userlist) ": 下面的调用方式,该正则的展开形式为"^ *(root|avahi|postfix|rpc|dbus) "。其含义为,以0个或多个空格开头,之后将是root、avahi、postfix、rpc或dbus之中的任何一个字符串,后面再跟随一个空格。
      if [ -z "$userlist" ]; then
          userlist="."
      else
          userlist="^ *($userlist) "
      fi
      #7. ps命令输出所有进程的user和命令信息,将结果传递给sed命令,sed将删除ps的title部分。
      #8. egrep过滤所有进程记录中,包含指定用户列表的进程记录,再将过滤后的结果传递给sort命令。
      #9. sort命令中的-b选项将忽略前置空格,并以user,再以进程名排序,将结果传递个uniq命令。
      #10.uniq命令将合并重复记录,-c选项将会使每条记录前加重复的行数。
      #11.第二个sort将再做一次排序,先以user,再以重复计数由大到小,最后以进程名排序。将结果传给awk命令。
      #12.awk命令将数据进行格式化,并删除重复的user。
      ps -eo user,comm | sed -e 1d | egrep "$userlist" |
          sort -b -k1,1 -k2,2 | uniq -c | sort -b -k2,2 -k1nr,1 -k3,3 |
              awk ' { user = (lastuser == $2) ? " " : $2;
                        lastuser = $2;
                        printf("%-15s\t%2d\t%s\n",user,$1,$3)
              }'
      CTRL+D
      /> ./test13.sh root avahi postfix rpc dbus
      avahi             2      avahi-daemon
      dbus             1      dbus-daemon
      postfix          1      pickup
                          1      qmgr
      root              5      mingetty
                          3      udevd
                          2      sort
                          2      sshd
      ... ...
      rpc               1      rpcbind

十四、用脚本完成which命令的基本功能:

      我们经常会在脚本中调用其他的应用程序,为了保证脚本具有更好的健壮性,以及错误提示的准确性,我们可能需要在执行前验证该命令是否存在,或者说是否可以被执行。这首先要确认该命令是否位于PATH变量包含的目录中,再有就是该文件是否为可执行文件。
      /> cat > test14.sh
      #!/bin/sh
      #1. 该函数用于判断参数1中的命令是否位于参数2所包含的目录列表中。需要说明的是,函数里面的$1和$2是指函数的参数,而不是脚本的参数,后面也是如此。
      #2. cmd=$1和path=$2,将参数赋给有意义的变量名,是一个很好的习惯。
      #3. 由于PATH环境变量中,目录之间的分隔符是冒号,因此这里需要临时将IFS设置为冒号,函数结束后再还原。
      #4. 在for循环中,逐个变量目录列表中的目录,以判断该命令是否存在,且为可执行程序。
      isInPath() {
          cmd=$1        path=$2      result=1
          oldIFS=$IFS   IFS=":"
          for dir in $path
          do
              if [ -x $dir/$cmd ]; then
                  result=0
              fi
          done
          IFS=oldifs
          return $result
      }
      #5. 检查命令是否存在的主功能函数,先判断是否为绝对路径,即$var变量的第一个字符是否为/,如果是,再判断它是否有可执行权限。
      #6. 如果不是绝对路径,通过isInPath函数判断是否该命令在PATH环境变量指定的目录中。
      checkCommand() {
          var=$1
          if [ ! -z "$var" ]; then
              if [ "${var:0:1}" = "/" ]; then
                  if [ ! -x $var ]; then
                      return 1
                  fi
              elif ! isInPath $var $PATH ; then
                  return 2
              fi
          fi
      }
      #7. 脚本参数的合法性验证。
      if [ $# -ne 1 ]; then
          echo "Usage: $0 command" >&2;
      fi
      #8. 根据返回值打印不同的信息。我们可以在这里根据我们的需求完成不同的工作。
      checkCommand $1
      case $? in
      0) echo "$1 found in PATH." ;;
      1) echo "$1 not found or not executable." ;;
      2) echo "$1 not found in PATH." ;;
      esac
      exit 0
      CTRL+D
      /> ./test14.sh echo
      echo found in PATH.
      /> ./test14.sh MyTest
      MyTest not found in PATH.
      /> ./test14.sh /bin/MyTest
      /bin/MyTest not found or not executable.


十五、验证输入信息是否合法:

      这里给出的例子是验证用户输入的信息是否都是数字和字母。需要说明的是,之所以将其收集到该系列中,主要是因为它实现的方式比较巧妙。
      /> cat > test15.sh
      #!/bin/sh
      echo -n "Enter your input: "
      read input
      #1. 事实上,这里的巧妙之处就是先用sed替换了非法部分,之后再将替换后的结果与原字符串比较。这种写法也比较容易扩展。    
      parsed_input=`echo $input | sed 's/[^[:alnum:]]//g'`
      if [ "$parsed_input" != "$input" ]; then
          echo "Your input must consist of only letters and numbers."
      else
          echo "Input is OK."
      fi
      CTRL+D
      /> ./test15.sh
      Enter your input: hello123
      Input is OK.
      /> ./test15.sh
      Enter your input: hello world
      Your input must consist of only letters and numbers.

十六、整数验证:

      整数的重要特征就是只是包含数字0到9和负号(-)。
      /> cat > test16.sh
      #!/bin/sh
      #1. 判断变量number的第一个字符是否为负号(-),如果只是则删除该负号,并将删除后的结果赋值给left_number变量。
      #2. "${number#-}"的具体含义,可以参考该系列博客中"Linux Shell常用技巧(十一)",搜索关键字"变量模式匹配运算符"即可。
      number=$1
      if [ "${number:0:1}" = "-" ]; then
          left_number="${number#-}"
      else
          left_number=$number
      fi
      #3. 将left_number变量中所有的数字都替换掉,因此如果返回的字符串变量为空,则表示left_number所包含的字符均为数字。
      nodigits=`echo $left_number | sed 's/[[:digit:]]//g'`
      if [ "$nodigits" != "" ]; then
          echo "Invalid number format!"
      else
          echo "You are valid number."
      fi
      CTRL+D
      /> ./test16.sh -123
      You are valid number.
      /> ./test16.sh 123e
      Invalid number format!
   
十七、判断指定的年份是否为闰年:

      这里我们先列出闰年的规则:
      1. 不能被4整除的年一定不是闰年;
      2. 可以同时整除4和400的年一定是闰年;
      3. 可以整除4和100,但是不能整除400的年,不是闰年;
      4. 其他可以整除的年都是闰年。
      #!/bin/sh   
      year=$1
      if [ "$((year % 4))" -ne 0 ]; then
          echo "This is not a leap year."
          exit 1
      elif [ "$((year % 400))" -eq 0 ]; then
          echo "This is a leap year."
          exit 0
      elif [ "$((year % 100))" -eq 0 ]; then
          echo "This is not a leap year."
          exit 1
      else
          echo "This is a leap year."
          exit 0
      fi
      CTRL+D
      /> ./test17.sh 1933
      This is not a leap year.
      /> ./test17.sh 1936
      This is a leap year.
           
十八、将单列显示转换为多列显示:

      我们经常会在显示时将单行的输出,格式化为多行的输出,通常情况下,为了完成该操作,我们将加入更多的代码,将输出的结果存入数组或临时文件,之后再重新 遍历它们,从而实现单行转多行的目的。在这里我们介绍一个使用xargs命令的技巧,可以用更简单、更高效的方式来完成该功能。   
      /> cat > test18.sh

      #!/bin/sh
      #1. passwd文件中,有可能在一行内出现一个或者多个空格字符,因此在直接使用cat命令的结果时,for循环会被空格字符切开,从而导致一行的文本被当 做多次for循环的输入,这样我们不得不在sed命令中,将cat输出的每行文本进行全局替换,将空格字符替换为%20。事实上,我们当然可以将cat /etc/passwd的输出以管道的形式传递给cut命令,这里之所以这样写,主要是为了演示一旦出现类似的问题该如果巧妙的处理。
      #2. 这里将for循环的输出以管道的形式传递给sort命令,sort命令将基于user排序。
      #3. -xargs -n 2是这个技巧的重点,它将sort的输出进行合并,-n选项后面的数字参数将提示xargs命令将多少次输出合并为一次输出,并传递给其后面的命令。在本 例中,xargs会将从sort得到的每两行数据合并为一行,中间用空格符分离,之后再将合并后的数据传递给后面的awk命令。事实上,对于awk而言, 你也可以简单的认为xargs减少了对它(awk)的一半调用。
      #4. 如果打算在一行内显示3行或更多的行,可以将-n后面的数字修改为3或其它更高的数字。你还可以修改awk中的print命令,使用更为复杂打印输出命令,以得到更为可读的输出效果。
      for line in `cat /etc/passwd | sed 's/ /%20/g'`
      do
          user=`echo $line | cut -d: -f1`
          echo $user
      done | \
          sort -k1,1 | \
          xargs -n 2 | \
          awk '{print $1, $2}'
      CTRL+D
      /> ./test18.sh
      abrt adm
      apache avahi
      avahi-autoipd bin
      daemon daihw
      dbus ftp
      games gdm
      gopher haldaemon
      halt lp
      mail nobody
      ntp operator
      postfix pulse
      root rtkit
      saslauth shutdown
      sshd sync
      tcpdump usbmuxd
      uucp vcsa

 

原文:Linux Shell高级技巧(三)

分享到:
评论

相关推荐

    Linux Shell高级技巧实战总结

    Linux Shell高级技巧实战总结 一、将输入信息转换为大写字符后再进行条件判断 二、为调试信息设置输出级别 三、判断参数是否为数字 四、判断整数变量的奇偶性 五、将Shell命令赋值给指定变量,以保证脚本的移植性 六...

    Linux Shell编程3/3

    Linux Shell编程经典著作: 第一部分SHELL |_文件安全与权限 |_..._…… 第五部分高级shell编程技巧 |_深入讨论|_shell工具 |_几个脚本例子 |_运行级别脚本 |_cgi脚本 附录常用shell命令

    高级shell编程 第五部分 高级shell编程技巧(共5部分)

    第五部分 高级shell编程技巧 第25章 深入讨论 第26章 shell 工 具 第27章 几个脚本例子 第28章 运行级别脚本 第29章 cgi 脚 本 附录 常用shell命令

    Shell高级编程(中文版)

    Shell高级编程(中文版) 毫无疑问,UNIX/Linux 最重要的软件之一就是 shell,目前最流行的 shell 被称为 Bash(Bourne Again Shell), 几乎所有的 Linux 和绝大部分的 UNIX 都可以使用 Bash。作为系统与用户之间的交互...

    实战Linux Shell编程与服务器管理-作者:卧龙小三(1)

    要达到这个境界,管理者必须具备相当程度的Shell操控能力与Shell程序设计能力,卧龙小三拥有丰富的主机管理实务经验,以及多年的教学经验,相信这本《实战Linux Shell编程与服务器管理》必能引领读者轻松跨越Bash ...

    LINUX与UNIX SHELL编程指南

    网上此书的目录很乱,而且一本书分割为好多文件。我详细整理了目录,并且合并为...第五部分 高级SHELL编程技巧 第二五章 深入讨论 第二六章 SHELL工具 第二七章 几个脚本例子 第二八章 运行级别脚本 第二九章 CGI脚本

    Linux Shell编程1/3

    Linux Shell编程经典著作: 第一部分SHELL |_文件安全与权限 |_..._…… 第五部分高级shell编程技巧 |_深入讨论|_shell工具 |_几个脚本例子 |_运行级别脚本 |_cgi脚本 附录常用shell命令

    Linux Shell编程2/3

    Linux Shell编程经典著作: 第一部分SHELL |_文件安全与权限 |_..._…… 第五部分高级shell编程技巧 |_深入讨论|_shell工具 |_几个脚本例子 |_运行级别脚本 |_cgi脚本 附录常用shell命令

    绝版经典 LINUX与UNIX SHELL编程指南 PDF 高清版 [16.3M]

    shell是一种完整的编程语言,易学易用;shell脚本可以使烦人的手工作业自动...第五部分 高级SHELL编程技巧 第二五章 深入讨论 第二六章 SHELL工具 第二七章 几个脚本例子 第二八章 运行级别脚本 第二九章 CGI脚本

    Linux shell编程指南.rar

    本文档是Linux shell编程指南教程,适于Linux编程新手,高清pdf。共分为5部分,第一部分:shell,第二部分:分文本过滤,第三部分:登陆环境,第四部分:shell编程,第五部分:高级shell编程技巧。

    Linux Shell 编程 入门、提高、精通

    第一部分 shell 第1章文件安全与权限 第2章使用find和xargs ...第五部分高级shell编程技巧 第25章深入讨论 第26章shell 工具 第27章几个脚本例子 第28章运行级别脚本 第29章cgi 脚本 附录常用shell命令

    LINUX与UNIX SHELL编程指南(很全)

    第三部分 登录环境 第13章 登录环境 125 13.1 /etc/profile 125 13.2 用户的$HOME.profile 128 13.3 stty用法 129 13.4 创建.logout文件 131 13.5 小结 131 第14章 环境和shell变量 132 14.1 什么是shell变量 132 ...

    Linux与unix+shell编程指南.pdf

    非常基础的shell编程文档主要分了五个部分 1.shell 2.文本过滤 3.登录环境 4.基础shell编程 5.高级shell编程技巧

    Linux shell编程指南

    本书共分五部分,详细介绍了shell编程技巧,各种UNIX命令及语法,还涉及了UNIX下的文字处理以及少量的系统管理问题。本书内容全面、文字简洁流畅,适合Shell编程人员学习、参考。 目 录 译者序 前言 第一部分 ...

    Shell初级和高级技巧

    Shell初级和高级技巧,在某大牛的的博客看到,然后自己整理归档,有需要的可以下载来看看(内附有博客地址)

    linux shell 编程教程

    linux shell编程 教程大全 目 录 译者序 前言 第一部分 shell 第1章 文件安全与权限 1 1.1 文件 1 1.2 文件类型 2 1.3 权限 2 1.4 改变权限位 4 1.4.1 符号模式 4 1.4.2 chmod命令举例 5 1.4.3 绝对模式 5 1.4.4 ...

    Linux命令学习 shell pdf格式

    第一部分 shell ...第五部分 高级shell编程技巧 第二十五章 深入讨论 第二十六章 shell工具 第二十七章 几个脚本例子 第二十八章 运行级别脚本 附录 常用shell命令 另外附有Linux命令说明(doc版,32页)

    Linux与unix shell编程指南

    本书共分五部分,详细介绍了shell编程技巧,各种UNIX命令及语法,还涉及了UNIX下的文字处理以及少量的系统管理问题。本书内容全面、文字简洁流畅,适合Shell编程人员学习、参考。 目 录 译者序 前言 第一部分 shell ...

    Linux与UNIX Shell编程指南.rar

    内容简介 本书共分五部分 ,详细介绍了SHELL编程技巧,各种UNIX命令及语法,还...第五部分 高级SHELL编程技巧 第二五章 深入讨论 第二六章 SHELL工具 第二七章 几个脚本例子 第二八章 运行级别脚本 第二九章 CGI脚本

Global site tag (gtag.js) - Google Analytics